LDAP AD无法验证我刚刚创建的用户

时间:2016-11-11 21:58:03

标签: java authentication active-directory ldap jndi

更新 11/14:我通过运营团队验证了通过Active Directory用户界面登录时用户名/密码是否有效。因此,它只是以编程方式失败。

我正在使用一个简单的Active Directory服务器,并且正在测试创建新用户的能力,然后使用我刚刚设置的凭据对该用户进行身份验证。

我可以成功验证现有用户(通过服务器上的管理界面创建);我可以创建一个新用户并设置密码(参见下面的代码片段);我可以成功找到该用户

但是,当我尝试使用我提供的凭据进行身份验证时,我正在获取

 javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db0]

以下是验证用户身份的代码

 public UserEntity authenticate ( @NotNull final String username,
                                  @NotNull final String password )
  throws NamingException
 {
     try
     {
        Hashtable<String, Object> env = new Hashtable<>();

        env.put( Context.SECURITY_AUTHENTICATION,"simple" );
        env.put( Context.SECURITY_PRINCIPAL,      username );
        env.put( Context.SECURITY_CREDENTIALS,    password );
        env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
        env.put( Context.PROVIDER_URL,            "ldaps://<host>:636" );
        env.put( Context.SECURITY_PROTOCOL,       "ssl" ) ;

        LdapContext context = new InitialLdapContext( env, null );

        // find the account now that the user is authenticated to 
        // construct the UserEntity
        // note: code for findAccountByAccountName() not included as
        //       the creation of the context is what generates the 
        //       exception
        return findAccountByAccountName( context, "<search-base>", username );
     }
  }

以下是创建新用户的代码

  public static void addUser( @NotNull final String username,
                              @NotNull final String firstName,
                              @NotNull final String password )
    throws NamingException
  {
    // Create a container set of attributes
    //
    Attributes container = new BasicAttributes(true); // case ignore

    // Create the object class to add
    Attribute objClasses = new BasicAttribute( "objectClass" );
    objClasses.add( "top" );
    objClasses.add( "person" );
    objClasses.add( "organizationalPerson" );
    objClasses.add( "user" );

    // Assign the username and first name
    //
    Attribute givenName = new BasicAttribute( "givenName", firstName );
    Attribute sAMAccountName = new BasicAttribute( "sAMAccountName", username );

    // Make the account active
    //
    Attribute userAccountControl = new BasicAttribute( "userAccountControl", "512" ) ;

    // Add these to the container
    //
    container.put( objClasses );
    container.put( givenName );
    container.put( sAMAccountName );
    container.put( userAccountControl ) ;

    // only can do this if connecting via secure ldap
    //
    if ( isSecureLdap() )
    {
       try
       {
          final String quotedPassword = String.format( "\"%s\"", password ) ;
          Attribute pwd = new BasicAttribute( "unicodePwd", quotedPassword.getBytes( "UTF-16LE" ) );
          container.put( pwd );
       }
       catch ( UnsupportedEncodingException e )
       {
          LOGGER.error( "Unable to encode password" );
       }
    }

    // creates a context using the Admin credentials.
    LdapContext context = setup() ;

    // Create the entry
    //
    context.createSubcontext( getUserDN( username ), container );
 }

然后在我的测试代码中:

 // authenticate a known user
 //
 try
 {
     // existing user 'dev' and this works just fine
     authenticate( "dev", "password" ) ;
 }
 catch ( NamingException e )
 {
     // if authentication fails, which it does not in this case
 }

 // create new user
 //
 final String username = "myTestUser" ;
 final String password = "myTestPassword" ;
 try
 {
     addUser( username, "test", password ) ;
 }
 catch ( NamingException e )
 {
     // if creation fails, which it does not in this case
 }

 // try to find that user 
 //
 try
 {
     // code for find() not included since it works
     final UserEntity user = findUser( username ) ;
 }
 catch ( NoSuchUserException e )
 {
     // thrown by find() if it fails -- again, this part still works
 }

 // attempt to authenticate the newly created user
 //
 try
 {
      authenticate( username, password ) ;
 }
 catch ( NamingException e )
 {
     // this is the part that throws the exception
 }

我确信这是一个很小的东西,但是在SO和其他地方搜索了很多东西之后,我还没有找到魔法豆来解决这个问题。

1 个答案:

答案 0 :(得分:0)

尝试使用密码代码:

private byte[] encodePassword(String pass) throws UnsupportedEncodingException 
{
     final String ATT_ENCODING = "Unicode"; 
     // Agree with MS's ATTRIBUTE_CONSTRAINT
     String pwd = "\"" + pass +"\"";
     byte bytes[] = pwd.getBytes(ATTENCODING); 
     // strip unicode marker
     byte bytes[] = new byte [_bytes.length - 2];
     System.arraycopy(_bytes, 2, bytes, 0,_bytes.length - 2);
     return bytes; 
}

Microsoft Active Directory对密码很有趣。 我们通常先添加用户然后修改密码。 -Jim