我正在使用基于 Windows 域登录的 SSO 的 Web 应用程序,为此我选择验证 Kerberos 票证。但现在我面临一个我找不到解决方案的问题。我设法无例外地验证票证,但是当我尝试获取用户名时,NullPointerException
会抛出,因为用户名是null
并且我不知道问题出在哪里。
如果我在验证期间没有收到任何异常,为什么用户名为空?
我如何获得用户名:
String clientName = gssContext.getSrcName().toString();
我基于此创建我的客户:
如何通过 GSS-API 获取 kerberos 服务票据?
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/single-signon.html
更新1:
我如何设置内容,只需在此处复制粘贴表单https://stackoverflow.com/a/25450862/1646082:
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();
更新 2:
如果我基于此https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension设置弹簧安全性,我也会遇到同样的错误:
java.lang.NullPointerException at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:136) at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:12 ) 在 java.security.AccessController.doPrivileged(Native Method) 在 javax.security.auth.Subject.doAs(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;
}
}
更新 3:
还尝试按照此处的建议将 Java 版本从 1.8 更改为 1.7使用 Kerberos 进行域身份验证失败。没有结果。
更新 4:
首先。不要使用 Java 1.8 b40 和 b45,它们都坏了。并且不要在本地PC上测试它,它不起作用(我不知道为什么)。
在更改最新(b65)Java 版本后,我得到了关于加密的异常(找不到适当类型的密钥来解密 AP REP - AES256 ...)。我已经通过 Java 1.8 的 Java Cryptography Extension (JCE) 修复了这个问题,并重新创建了 keytab,/crypto AES256-SHA1
毕竟我遇到了异常:
GSSException:在 sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) 在 sun.security.jgss.krb5.Krb5Context.acceptSecContext(Unknown Source) 的 GSS-API 级别未指定故障(机制级别:校验和失败) .jgss.GSSContextImpl.acceptSecContext(Unknown Source) at GssServer$GssServerAction.run(GssServer.java:159) ... 4 更多原因:KrbException: Checksum failed at sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(未知来源)在 sun.security.krb5.internal.crypto.ArcFourHmacEType.decrypt(未知来源)在 sun.security.krb5.EncryptedData.decrypt(未知来源)在 sun.security.krb5.KrbApReq.authenticate(未知来源)在sun.security.krb5.KrbApReq.(Unknown Source) at sun.security.jgss.krb5.InitSecContextToken.(Unknown Source) ... 8 更多原因:java.security。GeneralSecurityException: 校验和在 sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(Unknown Source) at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(Unknown Source) 处失败 ... 14 更多
我尝试了本教程和其他方法来创建 keytabfile,但我仍然没有解决方案。