AD LDS (ADAM)通过SSL修改密码



为了解决这个问题,我已经在网上搜索了好几天了。

我正在做一个项目,我有一个要求,允许用户使用ASP更改他们的密码。. NET web应用程序

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

我已经尝试了不同的代码变体:

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;
}

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

我得到一个异常在第二个版本在de.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingSsl;例外情况是"登录失败:未知用户名或错误密码"。

我得到一个异常在第三个版本在SearchResult sr = ds.FindOne();例外情况是"登录失败:未知用户名或错误密码"。

如果我尝试在端口389下使用AuthenticatioTypes运行此代码。无| AuthenticationTypes. NoneFastBind,它将在de.Invoke("ChangePassword", new object[] {pwd, newPwd})失败;除了"未知姓名"。我真的很想让它在SSL下运行,或者至少不传输任何密码。我的网站通过HTTPS运行。我确实尝试修改LDS上的dsHeuristics值,以便我可以通过非ssl连接更改密码,但这也不起作用。

如果有任何建议,我将不胜感激。

我终于能够让密码更改工作。我使用了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;
            }

最新更新