当 kerberos 票证过期时,Java 客户端挂起

Posted

技术标签:

【中文标题】当 kerberos 票证过期时,Java 客户端挂起【英文标题】:Java client hangs when kerberos ticket expires 【发布时间】:2017-10-23 17:28:49 【问题描述】:

我们已经实现了 Kerberos java 客户端,并且运行良好。但是,当 kerberos 票证到期时,Java 客户端应用程序会在控制台中询问用户名,这反过来会导致应用程序挂起。在 SoapUI 等工具中,我们观察到系统在 Kerberos 票证过期时抛出未经授权的错误。我们希望实现类似的行为,即如果 Kerberos 票证过期,应该抛出未经授权的错误,而不是等待用户输入凭据。请帮忙。

为 Kerberos 测试设置客户端系统 第 1 步:将密钥添加到 Windows 注册表: 项目价值 键 hkey_local_machine\system\currentcontrolset\control\lsa\kerberos 值名称 allowtgtsessionkey 值类型 reg_dword 值 0x01

第二步:在ClientKerberosAuthentication.java主类中添加一个java系统属性: System.setProperty("javax.security.auth.useSubjectCredsOnly","false");

第 3 步:获取票证授予票证 (tgt): 运行 kinit 实用程序以获取授予票证的票证。您可以在 /jre/bin 目录中找到此实用程序。 例如:C:\Program Files\Java\jdk1.7.0_79\bin\kinit spnuser7 密码:test@123

ClientKerberosAuthentication.java

public class ClientKerberosAuthentication  
    public static Credentials getCredentials() 

            return new NTCredentials("", "", "desktop.test.com", "test.com");

   
public static void main(String[] args) throws Exception 
    System.setProperty("sun.security.krb5.debug", "true");
    System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
    DefaultHttpClient httpclient = new DefaultHttpClient();
    try 
        httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory());
        Credentials use_jaas_creds = getCredentials();
        httpclient.getCredentialsProvider().setCredentials(
                new AuthScope(null, -1, null),
                use_jaas_creds);
        HttpUriRequest request = new HttpGet("http://kerbserver7.com/kerbservice/Service1.svc?wsdl");
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        System.out.println("----------------------------------------");
        if (entity != null) 
            System.out.println(EntityUtils.toString(entity));
        
        System.out.println("----------------------------------------");            
        EntityUtils.consume(entity);
     finally 
        httpclient.getConnectionManager().shutdown();
    
  

【问题讨论】:

您需要提供更多详细信息。你用过 JAAS 吗? @KevinO,我已经更新了更多细节。请看一看。 【参考方案1】:

我认为问题在于缺少 jaas 配置文件。应该有java.security.auth.login.config 的设置。在没有定义的 jaas.conf 文件的情况下,doNotPompt 设置为 false(表示会提示)。这与 OP 对提示的观察中描述的行为相匹配。

解决方案是创建一个 jaas 配置文件并使用上述属性指定所述文件。在上述 jaas.conf 文件中,设置doNotPrompt=true

例子:

com.sun.security.jgss.krb5.initiate 
  com.sun.security.auth.module.Krb5LoginModule required
  refreshKrb5Config=true
  useTicketCache=true
  renewTGT=true
  doNotPrompt=true
  useKeyTab=false
  storeKey=true
  debug=true
  ;
;

主要讨论在Krb5LoginModule的JavaDocs中

这里有一些额外的信息:http://cr.openjdk.java.net/~weijun/special/krb5winguide-2/raw_files/new/kwin

【讨论】:

@Arul,很高兴它有帮助。如果合适,请考虑接受答案,以帮助未来的人更轻松地找到此信息。干杯!

以上是关于当 kerberos 票证过期时,Java 客户端挂起的主要内容,如果未能解决你的问题,请参考以下文章

从授权标头中的 Kerberos 票证中读取用户名

如何使用 GSS API 更新 kerberos 服务票证

带有反应的 Kerberos 身份验证

来自 SSPI 的 KRB_AP_REQ 票证

Kerberos:应用服务器如何解密服务票据?

Kerberos 不签发可更新票证