Can't get Kerberos realm
원인 분석:
원래 코드는 다음과 같습니다.
org.apache.hadoop.security.UserGroupInformation.setConfiguration(conf)
sun.security.krb5.Config.refresh()
먼저 들어오는 Hadoop 설정 conf에 따라 UserGroupInformation(UGI)을 설정하고 방법의 호출 관계는 다음과 같다(관련 코드가 일부 삭제되었다).
public static void setConfiguration(Configuration conf) {
initialize(conf, true);
}
initialize 방법은 다음과 같다.
private static synchronized void initialize(Configuration conf, boolean overrideNameRules) {
authenticationMethod = SecurityUtil.getAuthenticationMethod(conf);
if (overrideNameRules || !HadoopKerberosName.hasRulesBeenSet()) {
try {
HadoopKerberosName.setConfiguration(conf);
} catch (IOException ioe) {
throw new RuntimeException(
"Problem with Kerberos auth_to_local name configuration", ioe);
}
}
......
}
setConfiguration 방법은 다음과 같습니다.
public static void setConfiguration(Configuration conf) throws IOException {
final String defaultRule;
switch (SecurityUtil.getAuthenticationMethod(conf)) {
case KERBEROS:
case KERBEROS_SSL:
try {
KerberosUtil.getDefaultRealm();
} catch (Exception ke) {
throw new IllegalArgumentException("Can't get Kerberos realm", ke);
}
......
}
......
}
Default Realm은 두 세트의 jdk, 즉 IBM(com.ibm.security.krb5.internal.Config)과 Oracle(sun.security.krb5.Config)을 호환하기 위해 반사를 사용했습니다.
public static String getDefaultRealm()
throws ClassNotFoundException, NoSuchMethodException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
Object kerbConf;
Class> classRef;
Method getInstanceMethod;
Method getDefaultRealmMethod;
if (System.getProperty("java.vendor").contains("IBM")) {
classRef = Class.forName("com.ibm.security.krb5.internal.Config"); // IBM jdk
} else {
classRef = Class.forName("sun.security.krb5.Config"); // Oracle jdk
}
getInstanceMethod = classRef.getMethod("getInstance", new Class[0]);
kerbConf = getInstanceMethod.invoke(classRef, new Object[0]);
getDefaultRealmMethod = classRef.getDeclaredMethod("getDefaultRealm", new Class[0]);
return (String)getDefaultRealmMethod.invoke(kerbConf, new Object[0]);
}
상기 코드를 보면, 먼저 Config 클래스 인용을 얻은 다음에 getInstanceMethod는 getInstance 방법을 얻고, 다시 getDefaultRealmMethod는 getDefaultRealm 방법을 얻는다.
따라서 우리가 Oracle의 JDK를 사용한다고 가정하면 마지막으로 호출된sun이다.security.krb5.getDefaultRealm().다음은 선.security.krb5.getDefaultRealm () 은 어떻게 이루어졌습니까?
public String getDefaultRealm() throws KrbException {
if(this.defaultRealm != null) { // defaultRealm , defaultRealm
return this.defaultRealm;
} else { // defaultRealm null, defaultRealm
KrbException var1 = null;
String var2 = this.getDefault("default_realm", "libdefaults");
if(var2 == null && this.useDNS_Realm()) {
try {
var2 = this.getRealmFromDNS();
} catch (KrbException var4) {
var1 = var4;
}
}
......
}
}
우리는defaultRealm =null을 가정하고 var2 =this에서 어떻게 하는지 봅시다.getRealmFromDNS();defaultRealm 가져오기
private String getRealmFromDNS() throws KrbException {
String var1 = null;
String var2 = null;
try {
var2 = InetAddress.getLocalHost().getCanonicalHostName(); // 1. local host name
} catch (UnknownHostException var7) {
KrbException var4 = new KrbException(60, "Unable to locate Kerberos realm: " + var7.getMessage());
var4.initCause(var7);
throw var4;
}
String var3 = PrincipalName.mapHostToRealm(var2); // 2. local host name realm
....
}
mapHostToRealm() 메서드는 다음과 같습니다.
static String mapHostToRealm(String var0) {
String var1 = null;
try {
String var2 = null;
Config var3 = Config.getInstance(); // Config
if((var1 = var3.getDefault(var0, "domain_realm")) != null) {
return var1;
}
.......
} catch (KrbException var5) {
;
}
return var1;
}
Config의 단일 예제 객체는 다음과 같습니다.
public static synchronized Config getInstance() throws KrbException {
if(singleton == null) {
singleton = new Config();
}
return singleton;
}
그리고 Config.getInstance();구체적인 동작은 단일 대상이 null인지 아닌지를 판단하고 null이 직접 되돌아오지 않고 null에 대해 다시 하나의 Config 대상을 만드는 것입니다.
또한 Config 클래스에는 다음과 같은 방법으로 refresh가 있습니다.
public static synchronized void refresh() throws KrbException {
singleton = new Config();
KdcComm.initStatic();
}
refresh의 코드로 볼 때refresh() 방법을 호출하면 Config의 단일 예시 대상이 다시 생성됩니다.이refresh () 방법도 우리 코드에서 호출해야 합니다.
우리의 원본 코드를 다시 한 번 살펴보자.
org.apache.hadoop.security.UserGroupInformation.setConfiguration(conf)
sun.security.krb5.Config.refresh()
getInstance () 방법으로 돌아가서singleton 단례가null라고 가정하면 Config의 단례 대상을 생성합니다.앞으로 getInstance 방법을 다시 호출하면 이 단일 대상을 직접 되돌려줍니다. 더 이상 new의 기회가 없습니다.new Config () 객체에 대한 찬스가 없다는 의혹이 제기되기 시작했습니다.Config 호출.refresh () 방법은 new가 되지 않습니까?답은 new일 수 있지만, 만약 우리의 UserGroupInformation이 있다면.setConfiguration(conf)에서 예외가 발생합니다.refresh () 방법은 호출되지 않습니다!우리의 오류는 바로 여기에 나타나서 UserGroupInformation을 분석하는 것이다.setConfiguration(conf)에서 예외가 발생한 경우
new Config()에서 구체적으로 어떤 일을 했는지 살펴보겠습니다.
private Config() throws KrbException {
String var1 = getProperty("java.security.krb5.kdc"); // kdc , JVM
if(var1 != null) {
this.defaultKDC = var1.replace(':', ' ');
} else {
this.defaultKDC = null;
}
this.defaultRealm = getProperty("java.security.krb5.realm"); // realm, JVM
if((this.defaultKDC != null || this.defaultRealm == null) && (this.defaultRealm != null || this.defaultKDC == null)) {
try {
String var3 = this.getJavaFileName(); // JVM java.security.krb5.conf /lib/security/krb5.conf krb5.conf
Vector var2;
if(var3 != null) {
var2 = this.loadConfigFile(var3);
this.stanzaTable = this.parseStanzaTable(var2);
if(DEBUG) {
System.out.println("Loaded from Java config");
}
} else { // JVM java.security.krb5.conf /lib/security/krb5.conf krb5.conf
boolean var4 = false;
if(isMacosLionOrBetter()) {
try {
this.stanzaTable = SCDynamicStoreConfig.getConfig();
if(DEBUG) {
System.out.println("Loaded from SCDynamicStoreConfig");
}
var4 = true;
} catch (IOException var6) {
;
}
}
if(!var4) {
var3 = this.getNativeFileName(); // centos , /etc/krb5.conf
var2 = this.loadConfigFile(var3); // /etc/krb5.conf
this.stanzaTable = this.parseStanzaTable(var2);
if(DEBUG) {
System.out.println("Loaded from native config");
}
}
}
} catch (IOException var7) {
;
}
} else {
throw new KrbException("System property java.security.krb5.kdc and java.security.krb5.realm both must be set or neither must be set.");
}
}
우리의 문제는 바로 var2 =this에서 나온다.loadConfigFile(var3);위치, 불러오기/etc/krb5.conf 파일을 만들 때/etc/krb5.conf 파일이 존재하지 않습니다. 수정된krb5.conf/etc/krb5 바꾸기conf 파일, 교체하는 시간 안에 loadConfig File () 로 가면 FileNotFoundException의 이상을 보고합니다.이 이상은 UserGroupInformation까지throw입니다.setConfiguration(conf)이 호출된 곳은 우리가Config를 영원히 호출하지 못하게 합니다.refresh () 방법.
2. 잘못 보고com.google.common.util.concurrent.UncheckedTimeoutException: java.util.concurrent.TimeoutException
원인 분석: 우선 이 이상은 상술한 오퍼를 디버깅하여 발생한 것이기 때문에 원인을 분석해 보겠습니다.
위의 오류는 Can't get Kerberos realm입니다. 인터넷에서 찾아보면 아마 kdc와realm을 받지 못했기 때문일 것입니다.
따라서 JVM 시작 매개변수에 다음과 같은 3개 매개변수를 추가했습니다.
-Djava.security.krb5.conf=/etc/krb5.conf \
-Djava.security.krb5.kdc=node1:8080 \
-Djava.security.krb5.realm=KFC.com \
krb5. 지정됨conf 파일, kdc 주소,realm 값.그리고 프로그램을 다시 시작하면 정상적으로 사용할 수 있음을 발견하고/etc/krb5.conf 파일이 삭제되었습니다. (이전 오류는krb5.conf를 읽지 못해서 일어난 것으로 추정됩니다.)
프로그램이 자바를 잘못 알다니.util.concurrent.TimeoutException, jstack
TimeoutException jstack :
"builtin-checker-serviceId-58" prio=10 tid=0x00007f678800e800 nid=0x4084 waiting for monitor entry [0x00007f672fffe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.apache.hadoop.security.UserGroupInformation.loginUserFromKeytabAndReturnUGI(UserGroupInformation.java:1074)
- waiting to lock <0x00000000a8b940d0> (a java.lang.Class for org.apache.hadoop.security.UserGroupInformation)
......
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
UserGroupInformation.loginUserFromKeytabAndReturnUGI block
jstack,
"builtin-checker-serviceId-59" prio=10 tid=0x00007f67680b3800 nid=0x4097 runnable [0x00007f672f2ee000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
- locked <0x000000009a0076e0> (a java.net.PlainDatagramSocketImpl)
at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:146)
- locked <0x000000009a0076e0> (a java.net.PlainDatagramSocketImpl)
at java.net.DatagramSocket.receive(DatagramSocket.java:816)
- locked <0x000000009a017848> (a java.net.DatagramPacket)
- locked <0x000000009a0076a0> (a java.net.DatagramSocket)
at sun.security.krb5.internal.UDPClient.receive(NetClient.java:207) //
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:390)
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:343)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.krb5.KdcComm.send(KdcComm.java:327)
at sun.security.krb5.KdcComm.send(KdcComm.java:219)
at sun.security.krb5.KdcComm.send(KdcComm.java:191)
at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319)
at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:735)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:584)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:687)
at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
at org.apache.hadoop.security.UserGroupInformation.loginUserFromKeytabAndReturnUGI(UserGroupInformation.java:1092)
- locked <0x00000000a8b940d0> (a java.lang.Class for org.apache.hadoop.security.UserGroupInformation)
........
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
jstack에서 UDPClient를 볼 수 있습니다.receive 카드 주인이야, 왜 카드 주인이야, 몰라!신에게 묻는다. 신은 JVM 디버깅 매개 변수를 넣겠다고 한다. - Dsun.security.krb5.debug=true, console에 로그를 출력할 수 있습니다.console에서 다음 로그를 볼 수 있습니다.
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 3 1 16.
default etypes for default_tkt_enctypes: 3 1 16.
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=node1 UDP:88, timeout=30000, number of retries =3, #bytes=134
>>> KDCCommunication: kdc=node1 UDP:88, timeout=30000,Attempt =1, #bytes=134
SocketTimeOutException with attempt: 1
>>> KDCCommunication: kdc=node1 UDP:88, timeout=30000,Attempt =2, #bytes=134
SocketTimeOutException with attempt: 2
>>> KDCCommunication: kdc=node1 UDP:88, timeout=30000,Attempt =3, #bytes=134
SocketTimeOutException with attempt: 3
>>> KrbKdcReq send: error trying node1
java.net.SocketTimeoutException: Receive timed out
at java.net.PlainDatagramSocketImpl.receive0(Native Method)
at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:146)
at java.net.DatagramSocket.receive(DatagramSocket.java:816)
at sun.security.krb5.internal.UDPClient.receive(NetClient.java:207)
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:390)
at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:343)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.krb5.KdcComm.send(KdcComm.java:327)
at sun.security.krb5.KdcComm.send(KdcComm.java:219)
at sun.security.krb5.KdcComm.send(KdcComm.java:191)
at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:319)
at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:364)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:735)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:584)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:687)
at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
at org.apache.hadoop.security.UserGroupInformation.loginUserFromKeytabAndReturnUGI(UserGroupInformation.java:1092)
........
기본적으로 KDC에 연결된 88포트를 보았는데 1088포트로 바뀌었기 때문에 연결이 실패하고 시간이 초과되었다.KDC의 포트를 설정할 수 있는 파라미터가 없다고 들었는데 진짜와 가짜를 몰라요. - Djava에서.security.krb5.kdc 매개 변수에서 지정한 kdc 포트가 잘못되었습니다.
참조:https://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/KerberosReq.html및 소스 코드
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.