2014-02-12 2 views
2

У меня есть пользовательское приложение для веб-серверов на основе Java, и мне нужно поддерживать Single-Sign-On. Я провел исследование по этой проблеме и выяснил, что я могу использовать JAAS для реализации SSO. Я уже настроил свой http-сервер, чтобы принять процесс установления подлинности аутентификации, поэтому у меня есть зарегистрированная пользовательская аутентификация, закодированная в моем приложении Java, и я передаю ей мою функцию аутентификации JAAS.
Теперь мне нужно аутентифицировать пользователя с помощью моего контроллера домена. Таким образом, я использую файл jaas.conf определить LoginModule:

Как интегрировать проверку подлинности Windows (SSO) в моем пользовательском веб-сервере на основе Java?

SSOAUTH { 
    com.sun.security.auth.module.Krb5LoginModule required 
    useKeyTab=false 
    storeKey=true 
    useTicketCache=false 
    debug=true; 
}; 

Как вы можете видеть, что я хотел бы использовать протокол Kerberos.
Первый вопрос: должен ли я сделать некоторую установку/настройку для моего контроллера домена для поддержки этого протокола?

Это мой Java-код в моем приложении веб-сервера, который будет обрабатывать весь процесс проверки подлинности с использованием JAAS:

public class LDAPClient 
{ 
    private static final String LOGIN_MODULE_NAME = "SSOAUTH"; 


/** 
* Constructor 
* @param domain 
* @param ldapServer 
* @param jaasConfigPath 
*/ 
public LDAPClient(String domain, String ldapServer, String jaasConfigPath) 
{ 
    System.setProperty("sun.security.krb5.debug", "true"); 
    System.setProperty("java.security.krb5.realm", domain); 
    System.setProperty("java.security.krb5.kdc", ldapServer); // LDAP active directory server name 
    System.setProperty("javax.security.auth.useSubjectCredsOnly", "true"); 
    System.setProperty("java.security.auth.login.config", jaasConfigPath); // path to the jaas.conf file. 
} 


/** 
* Authenticates the given kerberos token and returns the client principal. 
* 
* @param argKerberosTokenAsBase64 The kerberos content token. 
* @return 
* @throws Exception 
*/ 
public String authenticate(String argKerberosTokenAsBase64) throws Exception 
{ 
    BASE64Decoder decoder = new BASE64Decoder(); 
    byte[] kerberosToken = decoder.decodeBuffer(argKerberosTokenAsBase64.substring("Negotiate ".length())); 
    String clientName; 

    try 
    { 
     // Login to the KDC and obtain subject for the service principal 
     Subject subject = createServiceSubject(argKerberosTokenAsBase64); 
     if (subject != null) 
     { 
      clientName = acceptSecurityContext(subject, kerberosToken).toUpperCase(); 
      System.out.println("Security context successfully initialized!"); 
     } 
     else 
     { 
      throw new Exception("Unable to obtain kerberos service context"); 
     } 
    } 
    catch (Throwable throwable) 
    { 
     System.out.println("Token: " + argKerberosTokenAsBase64); 
     throwable.printStackTrace(); 
     throw new Exception(throwable); 
    } 

    return clientName; 
} 

/** 
* Creates service subject based on the service principal and service 
* password. 
* 
* @param password 
* @return 
* @throws LoginException 
*/ 
private static Subject createServiceSubject(String password) 
     throws LoginException 
{ 
    // "Client" references the JAAS configuration in the jaas.conf file. 
    LoginContext loginCtx = new LoginContext(LOGIN_MODULE_NAME, new LoginCallbackHandler(password)); 
    loginCtx.login(); 
    return loginCtx.getSubject(); 
} 

/** 
* Completes the security context initialisation and returns the client 
* name. 
* @param argSubject 
* @param serviceTicket 
* @return 
* @throws GSSException 
*/ 
private static String acceptSecurityContext(Subject argSubject, final byte[] serviceTicket) throws GSSException 
{ 
    // Accept the context and return the client principal name. 
    return (String) Subject.doAs(argSubject, new PrivilegedAction() 
    { 
     public Object run() 
     { 
      try 
      { 
       // Identify the server that communications are being made 
       // to. 
       GSSManager manager = GSSManager.getInstance(); 
       GSSContext context = manager.createContext((GSSCredential) null); 
       context.acceptSecContext(serviceTicket, 0, serviceTicket.length); 
       return context.getSrcName().toString(); 
      } 
      catch (GSSException exp) 
      { 
       throw new RuntimeException(exp); 
      } 
     } 
    }); 
} 

}


Я, имеющий следующую LoginException: javax .security.auth.login.LoginException: информация о предварительном подтверждении недействительна (24)

Я передаю токен аутентификации kerberos в LoginContext, см. Вызов createServiceSubject(), чтобы получить предмет, правильно ли он или что-то здесь отсутствует?

И это части от ошибки отладки System.out:

>>>KRBError: 
sTime is Wed Feb 12 14:29:17 IST 2014 1392208157000 
suSec is 301542 
error code is 25 
error Message is Additional pre-authentication required 
realm is DOMAIN.LOCAL 
sname is krbtgt/DOMAIN.LOCAL 
eData provided. 
msgType is 30 
>>>Pre-Authentication Data: 
PA-DATA type = 19 
PA-ETYPE-INFO2 etype = 23 
PA-ETYPE-INFO2 salt = null 
salt for 3 is DOMAIN.LOCALskadar 
>>>Pre-Authentication Data: 
PA-DATA type = 2 
PA-ENC-TIMESTAMP 
>>>Pre-Authentication Data: 
PA-DATA type = 16 
>>>Pre-Authentication Data: 
PA-DATA type = 15 
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ 
Updated salt from pre-auth = DOMAIN.LOCALskadar 
>>>KrbAsReq salt is DOMAIN.LOCALskadar 
Pre-Authenticaton: find key for etype = 3 
AS-REQ: Add PA_ENC_TIMESTAMP now 
>>> EType: sun.security.krb5.internal.crypto.DesCbcMd5EType 
+0

Возможно, вы захотите посмотреть SPNEGO. Существует реализация java на http://spnego.sourceforge.net/ – Qwerky

+0

. Я изучил это, но я не знаю, могу ли я использовать его с моим настраиваемым HTTP-сервером, потому что я знаю, что он может работать с известными серверами как Tomcat и т. д. – Snow

+0

Еще одна вещь, о которой я забыл упомянуть, заключается в том, что мне нужно поддерживать кросс-платформу SSO (windows, linux, ...) – Snow

ответ

Смежные вопросы