Var*_*lok 6 java kerberos jgss spring-security-kerberos
我正在使用基于Windows域登录的SSO进行Web应用,为此我选择验证Kerberos票证.但是现在我遇到了一个我无法找到解决方案的问题.我设法验证一个没有例外的票证,但当我试图获取userName时,NullPointerException
抛出,因为用户名是null
,我不知道哪里有问题.
如果在验证期间没有出现任何异常,为什么用户名为null?
我如何获得userName:
String clientName = gssContext.getSrcName().toString();
我基于此创建了我的客户端:
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/single-signon.html
更新1:
我如何设置内容,只需复制粘贴表格/sf/answers/1781560371/:
final Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
GSSManager gssmgr = GSSManager.getInstance();
// tell the GSSManager the Kerberos name of the service
GSSName serviceName = gssmgr.createName(this.servicePrincipal, GSSName.NT_USER_NAME);
// get the service's credentials. note that this run() method was called by Subject.doAs(),
// so the service's credentials (Service Principal Name and password) are already
// available in the Subject
GSSCredential serviceCredentials = gssmgr.createCredential(serviceName,
GSSCredential.INDEFINITE_LIFETIME, spnegoOid, GSSCredential.ACCEPT_ONLY);
// create a security context for decrypting the service ticket
GSSContext gssContext = gssmgr.createContext(serviceCredentials);
// decrypt the service ticket
System.out.println("Entering accpetSecContext...");
System.out.println( new String (Base64.encodeBase64( gssContext.acceptSecContext(this.kerberosTicket, 0,
this.kerberosTicket.length) ) ));
// get the client name from the decrypted service ticket
// note that Active Directory created the service ticket, so we can trust it
String clientName = gssContext.getSrcName().toString();
Run Code Online (Sandbox Code Playgroud)
更新2:
如果我根据此https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension设置spring security,我也会遇到同样的错误:
在显示java.lang.NullPointerException $ org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136)在org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator $ KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:125 )在javax.security.auth.Subject.doAs的java.security.AccessController.doPrivileged(Native Method)中(Subject.java:422)
private static class KerberosValidateAction implements PrivilegedExceptionAction<String> {
byte[] kerberosTicket;
public KerberosValidateAction(byte[] kerberosTicket) {
this.kerberosTicket = kerberosTicket;
}
@Override
public String run() throws Exception {
GSSContext context = GSSManager.getInstance().createContext((GSSCredential) null);
context.acceptSecContext(kerberosTicket, 0, kerberosTicket.length);
String user = context.getSrcName().toString(); // ERROR!
context.dispose();
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
更新3:
还尝试将Java版本从1.8更改为1.7,如此处所建议的,使用Kerberos进行域身份验证失败.没有结果.
更新4:
首先.不要使用Java 1.8 b40和b45,它们都被破坏了.并且不要在本地PC上测试它,它不起作用(我不知道为什么).
更改了最新的(b65)Java版本后,我得到了关于encription的异常(无法找到适当类型的密钥来解密AP REP - AES256 ......).我已经通过Java Cryptography Extension(JCE)修复了Java 1.8并重新创建了keytab,/crypto AES256-SHA1
毕竟我得到了异常:
GSSException:在sun.security的sun.security.jgss.GSSContextImpl.acceptSecContext(未知来源)sun.security.jgss.krb5.Krb5Context.acceptSecContext(未知来源)的GSS-API级别(机制级别:校验和失败)未指定失败GssServer上的.jgss.GSSContextImpl.acceptSecContext(未知来源)$ GssServerAction.run(GssServer.java:159)... 4更多引起:KrbException:在sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt上校验和失败(来自sun.security.krb5.KrbApReq.authenticate(未知来源)的sun.security.krb5.EncryptedData.decrypt(未知来源)sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(未知来源)的未知来源sun.security.krb5.KrbApReq.(未知来源),位于sun.security.jgss.krb5.InitSecContextToken.(未知来源)... 8更多引起:java.security.GeneralSecurityException:校验和在sun.security.krb5失败. sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(Unk)中的internal.crypto.dk.ArcFourCrypto.decrypt(未知来源)nown来源)......还有14个
我尝试了本教程和其他方法来创建keytabfile,但我仍然没有解决方案.
当您尝试获取 SrcName 时,上下文似乎尚未完全建立。这似乎是 ScrName 为空的原因。根据https://www-01.ibm.com/support/knowledgecenter/SSYKE2_7.0.0/com.ibm.java.security.api.doc/jgss/org/ietf/jgss/GSSContext.html,acceptSecContext ()生成一个令牌,如果它不为空,则应将该令牌发送给对等方。调用acceptSecContext()后,您应该检查isEstablished()是否返回false。如果是这样的话
如果此方法返回 false,则表示需要来自其对等方的令牌才能继续上下文建立阶段。返回值 true 表示上下文的本地端已建立。如果令牌是由 GSS-API 生成的,则这可能仍然需要将令牌发送到对等方。在上下文建立阶段,可以调用 isProtReady() 方法来确定上下文是否可用于每消息操作。这允许应用程序在未完全建立的上下文上使用每消息操作。
教程http://www.cs.mun.ca/java-api-1.5/guide/security/jgss/tutorials/BasicClientServer.html中更详细地解释了同样的内容:
AcceptSecContext 方法可能会返回一个令牌。如果是,接受者应将该令牌发送给发起者,然后发起者应再次调用 initSecContext 并将此令牌传递给它。每次 initSecContext 或acceptSecContext 返回令牌时,调用该方法的应用程序应将令牌发送给其对等方,而该对等方应将令牌传递给其适当的方法(acceptSecContext 或initSecContext)。这将一直持续到上下文完全建立(当上下文的 isEstablished 方法返回 true 时就是这种情况)。