具有null SrcName的GSSContext

我正在使用基于Windows域登录的SSO进行Web应用程序,为此我选择validationKerberos票证。 但是现在我遇到了一个我无法找到解决方案的问题。 我设法validation没有exception的票证,但是当我试图获取userName时,抛出NullPointerException ,因为用户名为null ,我不知道问题出在哪里。

如果在validation期间没有出现任何exception,为什么用户名为null?

我如何得到userName: String clientName = gssContext.getSrcName().toString();

我基于此创建了我的客户端:

使用GSSManagervalidationKerberos票证

如何通过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设置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 { 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进行域身份validation失败 。 没有结果。

更新4:

首先。 不要使用Java 1.8 b40和b45,它们都破坏了。 并且不要在本地PC上测试它,它不起作用(我不知道为什么)。

更改了最新的(b65)Java版本后,我得到了关于encription的exception(无法找到适当类型的密钥来解密AP REP – AES256 ……)。 我已经通过Java Cryptography Extension(JCE)修复了Java 1.8,并在我得到exception之后用/crypto AES256-SHA1重新创建了keytab:

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。(未知来源)at 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,但我仍然没有解决方案。

在实现我的GSSAPI套接字演示时,我遇到了相同的Checksum failed错误,这是对Oracle GSSAPI 教程代码的修改。 我在注册FreeIPA kerberos领域的Linux机器上执行了我的代码。 我使用过Linux系统的vanilla krb5.conf文件。 票证类型没有限制:

 ... [libdefaults] default_realm = AUTHDEMO.IT dns_lookup_realm = true dns_lookup_kdc = true rdns = false ticket_lifetime = 24h forwardable = true udp_preference_limit = 0 ... 

FreeIPA领域默认使用18型票证(AES-256)。

关于我的应用程序,它配置了以下策略文件:

 grant CodeBase "file:./app.jar" { permission java.security.AllPermission; }; grant CodeBase "file:./app.jar" Principal javax.security.auth.kerberos.KerberosPrincipal "servicename@AUTHDEMO.IT" { permission java.net.SocketPermission "*", "accept"; permission javax.security.auth.kerberos.ServicePermission "servicename@AUTHDEMO.IT", "accept"; }; 

执行应用程序时,我在接受方面遇到此错误:

GSSException:GSS-API级别未指定失败(机制级别:不支持/启用HMAC SHA1-96的加密类型AES256CTS模式)

在我的情况下,错误出现在GSS接受方。 在我的应用程序中,我以编程方式生成Jaas配置(我将在此处称为DConfig )并且我不使用配置文件。 我发现,第一个解决方案是使用配置文件而不是DConfig,问题就消失了,它运行正常。 临时解决方案,Jaas Config文件:

 DemoServer { com.sun.security.auth.module.Krb5LoginModule required principal="servicename@AUTHDEMO.IT" storeKey=true debug=true; #not mandatory }; 

使用此配置,接收方不会出现问题,应用程序可以检查服务票证的有效性并接受连接。

我问自己.. 为什么?

我检查了使用这两种配置获得的主题的差异。 在工作案例中,使用配置文件,主题在私有凭证中包含密码哈希凭证和主要TGT票证。 使用DConfig,我获得一个只有密码哈希的主题,但私有凭证中没有主要的TGT票证。

我的修复

DConfig包含配置文件的相同设置,其他选项是Krb5LoginModule默认值的副本,起初我看不出错误行为的原因。

设置isInitiator = true ,进入受体端DConfig,解决了问题。 `isInitiator = true强制TGT票证的持久性进入主题。

使用此解决方法,错误消失,系统krb5.conf没有更改。

我的分是……在Jaas登录之后,让我们检查您的主题私人凭证是否缺乏信用(您需要服务主体TGT进入您的接受方主题!)并且万一尝试将isInitiator = true设置为接受方。

问候

当您尝试获取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时)。