2012-10-29 5 views
3

Linux 컴퓨터에서 실행되는 Java에서 Active Directory 인증을 구현하려고합니다. test2.ad2.bar.com을 신뢰신뢰할 수있는 도메인에서의 Java AD 인증

test1.ad1.foo.com : 우리의 AD 설정은 그래서 우리의 테스트 환경을 위해 우리는 두 개의 도메인 컨트롤러가 서로 신뢰 관계를 공유하는 여러 서버로 구성됩니다.

내가 성공적으로하지 test2test1에서 사용자를 인증 할 수 있지만, 아래의 코드를 사용하여 : trust1trust2에서 사용자의 로그인 시도를받는 경우 나, 신뢰 관계의 이해가 무엇에서

public class ADDetailsProvider implements ResultSetProvider { 
private String domain; 
private String user; 
private String password; 

public ADDetailsProvider(String user, String password) { 
    //extract domain name 
    if (user.contains("\\")) { 
     this.user = user.substring((user.lastIndexOf("\\") + 1), user.length()); 
     this.domain = user.substring(0, user.lastIndexOf("\\")); 
    } else { 
     this.user = user; 
     this.domain = ""; 
    } 

    this.password = password; 
} 

    /* Test from the command line */ 
public static void main (String[] argv) throws SQLException { 
    ResultSetProvider res = processADLogin(argv[0], argv[1]); 
    ResultSet results = null; 
    res.assignRowValues(results, 0); 
    System.out.println(argv[0] + " " + argv[1]); 
} 


public boolean assignRowValues(ResultSet results, int currentRow) 
    throws SQLException 
{ 
    // Only want a single row 
    if (currentRow >= 1) return false; 

    try { 
     ADAuthenticator adAuth = new ADAuthenticator(); 
     LdapContext ldapCtx = adAuth.authenticate(this.domain, this.user, this.password); 
     NamingEnumeration userDetails = adAuth.getUserDetails(ldapCtx, this.user); 

     // Fill the result set (throws SQLException). 
     while (userDetails.hasMoreElements()) { 
      Attribute attr = (Attribute)userDetails.next(); 
      results.updateString(attr.getID(), attr.get().toString()); 
     } 

     results.updateInt("authenticated", 1); 
     return true; 

    } catch (FileNotFoundException fnf) { 
     Logger.getAnonymousLogger().log(Level.WARNING, 
      "Caught File Not Found Exception trying to read cris_authentication.properties"); 

     results.updateInt("authenticated", 0); 
     return false; 

    } catch (IOException ioe) { 
     Logger.getAnonymousLogger().log(Level.WARNING, 
      "Caught IO Excpetion processing login"); 

     results.updateInt("authenticated", 0); 
     return false; 

    } catch (AuthenticationException aex) { 
     Logger.getAnonymousLogger().log(Level.WARNING, 
      "Caught Authentication Exception attempting to bind to LDAP for [{0}]", 
      this.user); 

     results.updateInt("authenticated", 0); 
     return true; 

    } catch (NamingException ne) { 
     Logger.getAnonymousLogger().log(Level.WARNING, 
      "Caught Naming Exception performing user search or LDAP bind for [{0}]", 
      this.user); 
     results.updateInt("authenticated", 0); 
     return true; 
    } 
} 

public void close() { 
    // nothing needed here 
} 

/** 
* This method is called via a Postgres function binding to access the 
* functionality provided by this class. 
*/ 
public static ResultSetProvider processADLogin(String user, String password) { 
    return new ADDetailsProvider(user, password); 
} 
} 

public class ADAuthenticator { 

public ADAuthenticator() 
    throws FileNotFoundException, IOException { 
    Properties props = new Properties(); 
    InputStream inStream = this.getClass().getClassLoader(). 
     getResourceAsStream("com/bar/foo/ad/authentication.properties"); 

    props.load(inStream); 
    this.domain    = props.getProperty("ldap.domain"); 
    inStream.close(); 
} 

public LdapContext authenticate(String domain, String user, String pass) 
    throws AuthenticationException, NamingException, IOException { 
    Hashtable env = new Hashtable(); 
    this.domain = domain; 

    env.put(Context.INITIAL_CONTEXT_FACTORY, com.sun.jndi.ldap.LdapCtxFactory); 
    env.put(Context.PROVIDER_URL, "ldap://" + test1.ad1.foo.com + ":" + 3268); 
    env.put(Context.SECURITY_AUTHENTICATION, simple); 
    env.put(Context.REFERRAL, follow); 

    env.put(Context.SECURITY_PRINCIPAL, (domain + "\\" + user)); 
    env.put(Context.SECURITY_CREDENTIALS, pass); 

    // Bind using specified username and password 
    LdapContext ldapCtx = new InitialLdapContext(env, null); 
    return ldapCtx; 
} 

public NamingEnumeration getUserDetails(LdapContext ldapCtx, String user) 
    throws NamingException { 
    // List of attributes to return from LDAP query 
    String returnAttributes[] = {"ou", "sAMAccountName", "givenName", "sn", "memberOf"}; 

    //Create the search controls 
    SearchControls searchCtls = new SearchControls(); 
    searchCtls.setReturningAttributes(returnAttributes); 

    //Specify the search scope 
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); 

    // Specify the user to search against 
    String searchFilter = "(&(objectClass=*)(sAMAccountName=" + user + "))"; 

    //Perform the search 
    NamingEnumeration answer = ldapCtx.search("dc=dev4,dc=dbt,dc=ukhealth,dc=local", searchFilter, searchCtls); 

    // Only care about the first tuple 
    Attributes userAttributes = ((SearchResult)answer.next()).getAttributes(); 
    if (userAttributes.size() <= 0) throw new NamingException(); 

    return (NamingEnumeration) userAttributes.getAll(); 
} 

, 로그인 시도를 전달해야하며 사용자의 도메인 이름에서이를 처리합니다.

이것이 맞습니까? 아니면 누락 되었습니까? 아니면 위의 방법을 사용하여 가능하지 않습니까?

--EDIT--
LDAP 바인드에서 스택 추적 {java.naming.provider.url=ldap://test1.ad1.foo.com:3268, java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory, java.naming.security.authentication=simple, java.naming.referral=follow} 30-Oct-2012 13:16:02
ADDetailsProvider assignRowValues WARNING: Caught Authentication Exception attempting to bind to LDAP for [trusttest] Auth error is [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db0]

답변

0

는 지금까지 내가 아는 한, true로 Context.REFERRAL을 설정해야합니다.
이것은 코드에서 의미 한 것입니까?
또한 GSSAPI/Kerberos로 전환했을 때
Kerberos 영역 간의 트러스트 관계가 정의되어있어 저에게 효과적이었습니다.

+0

나는이 가이드 [링크] (http://docs.oracle.com/javase/jndi/tutorial/ldap/referral/jndi.html)를보고 따라갈 방법을 설정했습니다. 설정을 시도했습니다. _true_하지만 이름 지정 예외가 발생합니다. 답장을 보내 주셔서 감사합니다! – benjstephenson

+0

가지고있는 NamingException에 대한 정보를 제공해주십시오. –

+0

참조 메소드를 _true_로 설정 한 스택 유예가'javax.naming.NoInitialContextException : 해시 테이블에 지정된 팩토리를 사용하여 InitialContext를 작성하는 데 실패했습니다. [루트 예외는 java.lang.IllegalArgumentException : java.naming.referral 속성에 대한 잘못된 값입니다. ' 감사. – benjstephenson

관련 문제