2011-07-22 80 views
0

我一直在寻找互联网试图解决这个问题的日子。AD LDS(ADAM)通过SSL更改密码

我工作的一个项目,我有允许用户改变使用ASP.NET Web应用程序密码的要求。

我必须使用“ChangePassword”,而不是“SetPassword”因为我必须强制密码历史记录,并且不允许任何用户在任何LDS更多的特权比他们的需要。我正在尝试在开发环境中完成此任务。我有两台机器“Server1”(LDS,PingFederate,CA)和“Server2”(IIS)。我想我可能会遇到问题,因为我没有在两个盒子之间设置SSL,所以我昨天花了半天的时间建立一个CA并为两台机器创建了证书。我相当确定它正在工作,因为我不再在错误日志中看到任何错误,并且我可以使用端口636使用LDP使用LDP登录到LDS并检查SSL。我还应该提到这些机器不在域环境中。我已经在测试网络上的所有机器上编辑了主机文件。

我曾尝试的代码不同的变化:

public static bool ChangePassword(string email, string pwd, string newPwd) 
{ 
    DirectoryEntry user = GetCN(email); 
    string username = user.Properties["cn"][0].ToString(); 

    DirectoryEntry de = new DirectoryEntry(); 
    de.AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer; 
    de.Path = user.Path; 
    de.Username = username; 
    de.Password = pwd; 
    try 
    { 
     Object obj = de.NativeObject; 
     de.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingSsl; 
     de.Options.PasswordPort = Convert.ToInt32(ConfigurationManager.AppSettings["LDAPPort_ExternalUsers"]); 
     de.Invoke("ChangePassword", new object[] { pwd, newPwd }); 
     de.CommitChanges(); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     return false; 
    } 
} 

public static bool ChangePassword(string email, string pwd, string newPwd) 
{ 
    DirectoryEntry user = GetCN(email); 
    string username = user.Properties["cn"][0].ToString(); 

    DirectoryEntry de = new DirectoryEntry(user.Path, username, pwd, AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer); 
    try 
    { 
     de.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingSsl; 
     de.Options.PasswordPort = Convert.ToInt32(ConfigurationManager.AppSettings["LDAPPort_ExternalUsers"]); 
     de.Invoke("ChangePassword", new object[] { pwd, newPwd }); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     return false; 
    } 
} 

public static bool ChangePassword(string email, string pwd, string newPwd) 
{ 
    DirectoryEntry userInc = GetCN(email); 
    string username = userInc.Properties["cn"][0].ToString(); 

    using (DirectoryEntry searchRoot = new DirectoryEntry(ConfigurationManager.AppSettings["LDAPConnectionString_ExternalUsers"], username, pwd, AuthenticationTypes.SecureSocketsLayer | AuthenticationTypes.Secure)) 
    using (DirectorySearcher ds = new DirectorySearcher(searchRoot)) 
    { 
     ds.Filter = "(|(objectCategory=user)(cn=" + username + "))"; 
     SearchResult sr = ds.FindOne(); 
     if (sr != null) 
     { 
      using (DirectoryEntry user = sr.GetDirectoryEntry()) 
      { 
       user.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingClear; 
       user.Options.PasswordPort = Convert.ToInt32(ConfigurationManager.AppSettings["LDAPPort_ExternalUsers"]); 
       //user.Invoke("SetOption", new object[] { 6, Convert.ToInt32(ConfigurationManager.AppSettings["LDAPPort_ExternalUsers"]) }); 
       //user.Invoke("SetOption", new object[] { 7, 1 }); 
       user.Invoke("ChangePassword", new object[] { pwd, newPwd }); 
      } 
      return true; 
     } 
    } 
    return false; 
} 

我得到在对象中的第一版本的异常OBJ = de.NativeObject ;.我正在使用它来确定绑定是否正确发生,并作为调试步骤插入,因为这是我通过端口389验证用户的方式。例外是“登录失败:未知用户名或错误密码”。

我在de.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingSsl获得的第二个版本的除外;例外是“登录失败:未知的用户名或错误的密码”。

我得到的第三个版本的异常在信息搜索结果SR = ds.FindOne();例外是“登录失败:未知的用户名或错误的密码”。

如果我不尝试下端口389 AuthenticatioTypes.None运行这段代码| AuthenticationTypes.FastBind,它会在de.Invoke(“ChangePassword”,新对象[] {pwd,newPwd});除“未知名称”外。我真的很想在SSL下运行,或者至少不要传输任何密码。我确实通过HTTPS运行了该网站。我曾尝试修改LDS上的dsHeuristics值,以便我可以对非SSL连接进行密码更改,但这也不起作用。

任何建议,任何人都可能会被大加赞赏。

回答

0

我终于可以获得密码更改工作。我用我用这三个功能呈现在http://www.informit.com/articles/article.aspx?p=474649&seqNum=4

的信息:

private static DirectoryConnection GetConnection(string server, NetworkCredential credential, bool useSsl) 
{ 
LdapConnection connection = 
    new LdapConnection(server); 

    if (useSsl) 
    { 
      connection.SessionOptions.SecureSocketLayer = true; 
    } 
    else 
    { 
      connection.SessionOptions.Sealing = true; 
    } 

    connection.Bind(credential); 
    return connection; 
} 

private static void ChangePassword(DirectoryConnection connection, string userDN, string oldPassword, string newPassword) 
{ 
    DirectoryAttributeModification deleteMod = new DirectoryAttributeModification(); 
    deleteMod.Name = "unicodePwd"; 
    deleteMod.Add(GetPasswordData(oldPassword)); 
    deleteMod.Operation= DirectoryAttributeOperation.Delete; 

    DirectoryAttributeModification addMod = new DirectoryAttributeModification(); 
    addMod.Name = "unicodePwd"; 
    addMod.Add(GetPasswordData(newPassword)); 
    addMod.Operation = DirectoryAttributeOperation.Add; 

    ModifyRequest request = new ModifyRequest(userDN, deleteMod, addMod); 

    DirectoryResponse response = connection.SendRequest(request); 
} 

private static byte[] GetPasswordData(string password) 
{ 
    string formattedPassword; 
    formattedPassword = String.Format("\"{0}\"", password); 
    return (Encoding.Unicode.GetBytes(formattedPassword)); 
} 

我打电话从页面背后的代码,像这样的功能,允许修改密码:

NetworkCredential credential = new NetworkCredential("[user with access to the LDS", "pwd"); 
      DirectoryConnection connection; 
      try 
      { 
       //Setup our connection 
       connection = ADAuth.GetConnection(ConfigurationManager.AppSettings["LDAPServer_ExternalUsers"] + ":" + ConfigurationManager.AppSettings["LDAPPort_ExternalUsers"], credential, true); 

       //Attempt to change the password 
       ADAuth.ChangePassword(connection, ADAuth.GetDN(userID.Text).Properties["distinguishedName"].Value.ToString(), currPass.Text, newPass.Text); 

       //Send success message to user 
       ErrorLit.Text = "<p>Password change successful!</p>"; 
       //Dispose the connection 
       IDisposable disposable = connection as IDisposable; 
       if (disposable != null) 
        disposable.Dispose(); 
      } 
      catch (Exception ex) 
      { 
       //There was an error, tell the user 
       errors += "<li>Error changing password</li>"; 
       ErrorLit.Text = errors + "</ul>"; 
       return; 
      }