2014-04-01 40 views
0

以下是我用於嘗試Active Directory身份驗證(基於此Spring源代碼http://goo.gl/qRFNKY)的示例Kerberos JAAS客戶端。對於具有國際字符的用戶,JAAS Kerberos身份驗證失敗

我能夠在名稱和密碼只包含英文字符時對用戶進行身份驗證。

//works 
client.login("[email protected]", "Password1"); 

當任何一個字段包含國際字符時,它將失敗。

//fails 
client.login("áá@MYDOMAIN.COM", "çã123"); 

如何國際化此代碼?

package aa; 

import java.io.IOException; 
import java.util.HashMap; 

import javax.security.auth.callback.Callback; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.callback.NameCallback; 
import javax.security.auth.callback.PasswordCallback; 
import javax.security.auth.callback.UnsupportedCallbackException; 
import javax.security.auth.login.AppConfigurationEntry; 
import javax.security.auth.login.Configuration; 
import javax.security.auth.login.LoginContext; 
import javax.security.auth.login.LoginException; 


public class SampleKerberosClient { 

    public static void main(String[] args) throws LoginException { 
     SampleKerberosClient client = new SampleKerberosClient(); 

     //works 
      client.login("[email protected]", "Password1"); 

     //fails 
      client.login("áá@MYDOMAIN.COM", "çã123"); 

    } 

    private boolean debug = true; 
    private String krbConfLocation = "/Users/aa/java/jaas/src/aa/krb5.conf"; 

    public SampleKerberosClient() { 
     System.setProperty("java.security.krb5.conf", krbConfLocation); 
     System.setProperty("sun.security.krb5.debug", "true"); 
    } 

    public String login(String username, String password) throws LoginException { 
     System.out.println("Trying to authenticate " + username + " with Kerberos"); 
     String validatedUsername; 

     LoginContext loginContext = new LoginContext("", null, new KerberosClientCallbackHandler(username, password), 
       new LoginConfig(this.debug)); 
     loginContext.login(); 
     System.out.println("Kerberos authenticated user: " + loginContext.getSubject()); 
     validatedUsername = loginContext.getSubject().getPrincipals().iterator().next().toString(); 
     loginContext.logout(); 

     System.out.println("validated user name: " + validatedUsername); 
     return validatedUsername; 

    } 


    private static class LoginConfig extends Configuration { 
     private boolean debug; 

     public LoginConfig(boolean debug) { 
      super(); 
      this.debug = debug; 
     } 

     @Override 
     public AppConfigurationEntry[] getAppConfigurationEntry(String name) { 
      HashMap<String, String> options = new HashMap<String, String>(); 
      options.put("storeKey", "true"); 
      if (debug) { 
       options.put("debug", "true"); 
      } 

      return new AppConfigurationEntry[]{new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", 
        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options),}; 
     } 
    } 

    private static class KerberosClientCallbackHandler implements CallbackHandler { 
     private String username; 
     private String password; 

     public KerberosClientCallbackHandler(String username, String password) { 
      this.username = username; 
      this.password = password; 
     } 

     @Override 
     public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
      for (Callback callback : callbacks) { 
       if (callback instanceof NameCallback) { 
        NameCallback ncb = (NameCallback) callback; 
        ncb.setName(username); 
       } else if (callback instanceof PasswordCallback) { 
        PasswordCallback pwcb = (PasswordCallback) callback; 
        pwcb.setPassword(password.toCharArray()); 
       } else { 
        throw new UnsupportedCallbackException(callback, "We got a " + callback.getClass().getCanonicalName() 
          + ", but only NameCallback and PasswordCallback is supported"); 
       } 
      } 
     } 
    } 
} 

下面是控制檯輸出(如果失敗)

Trying to authenticate áá@MYDOMAIN.COM with Kerberos 
Debug is true storeKey true useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false 
     [Krb5LoginModule] user entered username: áá@MYDOMAIN.COM 

Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17 18. 
Acquire TGT using AS Exchange 
>>> KdcAccessibility: reset 
Using builtin default etypes for default_tkt_enctypes 
default etypes for default_tkt_enctypes: 3 1 23 16 17 18. 
>>> KrbAsReq calling createMessage 
>>> KrbAsReq in createMessage 
>>> KrbKdcReq send: kdc=ADSERVER.MYDOMAIN.COM.com UDP:88, timeout=30000, number of retries =3, #bytes=179 
>>> KDCCommunication: kdc=ADSERVER.MYDOMAIN.COM UDP:88, timeout=30000,Attempt =1, #bytes=179 
>>> KrbKdcReq send: #bytes read=116 
>>> KrbKdcReq send: #bytes read=116 
>>> KdcAccessibility: remove ADSERVER.MYDOMAIN.COM. 
>>> KDCRep: init() encoding tag is 126 req type is 11 
>>>KRBError: 
    sTime is Mon Mar 31 17:10:03 PDT 2014 1396311003000 
    suSec is 268438 
    error code is 6 
    error Message is Client not found in Kerberos database 
    realm is MYDOMAIN.COM 
    sname is krbtgt/MYDOMAIN.COM 
    msgType is 30 
     [Krb5LoginModule] authentication failed 
Client not found in Kerberos database (6) 
Exception in thread "main" javax.security.auth.login.LoginException: Client not found in Kerberos database (6) 
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:696) 
    at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769) 
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186) 
    at javax.security.auth.login.LoginContext$5.run(LoginContext.java:706) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.login.LoginContext.invokeCreatorPriv(LoginContext.java:703) 
    at javax.security.auth.login.LoginContext.login(LoginContext.java:575) 
    at aa.SampleKerberosClient.login(SampleKerberosClient.java:45) 
    at aa.SampleKerberosClient.main(SampleKerberosClient.java:27) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 
Caused by: KrbException: Client not found in Kerberos database (6) 
    at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:66) 
    at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:446) 
    at sun.security.krb5.Credentials.sendASRequest(Credentials.java:419) 
    at sun.security.krb5.Credentials.acquireTGT(Credentials.java:368) 
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:662) 
    ... 18 more 
Caused by: KrbException: Identifier doesn't match expected value (906) 
    at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133) 
    at sun.security.krb5.internal.ASRep.init(ASRep.java:58) 
    at sun.security.krb5.internal.ASRep.<init>(ASRep.java:53) 
    at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:50) 
    ... 22 more 

回答

0

我已經回答過類似的問題,搜索愛爾蘭發達和Kerberos。顯然,KerberosLoginModule不會正確地將字符轉換爲字節。它應該生成一個UTF-8字節序列。您應該使用Wireshark檢查流量。

+0

你確認是有幫助的。然後下一步驟是潛入Krb5LoginModule源。如果我找到有用的東西,我會發布。 – akirekadu

+0

@akirekadu,*不*。首先使用Wireshark。 –