Java 具有国际字符的用户的JAAS Kerberos身份验证失败

Java 具有国际字符的用户的JAAS Kerberos身份验证失败,java,authentication,active-directory,kerberos,jaas,Java,Authentication,Active Directory,Kerberos,Jaas,下面是一个示例Kerberos JAAS客户机,我用于基于此Spring源代码尝试Active Directory身份验证 当用户名和密码仅包含英文字符时,我可以对用户进行身份验证 //works client.login("joe@MYDOMAIN.COM", "Password1"); 当任一字段包含国际字符时,它将失败 //fails client.login("áá@MYDOMAIN.COM", "çã123"); 如何将此代码国际化 package aa; import java

下面是一个示例Kerberos JAAS客户机,我用于基于此Spring源代码尝试Active Directory身份验证

当用户名和密码仅包含英文字符时,我可以对用户进行身份验证

//works
client.login("joe@MYDOMAIN.COM", "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("joe@MYDOMAIN.COM", "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

我已经回答了一个类似的问题,搜索爱尔兰Fada和Kerberos。KerberosLoginModule显然无法将字符正确地转换为字节。它应该生成一个UTF-8字节序列。您应该与Wireshark一起检查流量。

您的确认很有帮助。接下来的一步是深入了解Krb5LoginModule源代码。如果我发现任何有用的东西,我会发布。@akirekadu,不要。首先使用Wireshark。