AD LDS (ADAM) 通过 SSL 更改密码
我已经在互联网上搜索了好几天试图解决这个问题。
我正在开发一个项目,需要允许用户使用 ASP.NET Web 应用程序更改密码。
我必须使用“ChangePassword”而不是“SetPassword”,因为我必须强制执行密码历史记录,并且不允许 LDS 中的任何用户拥有超出其需要的权限。我正在尝试在开发环境中完成此任务。我有两台机器“Server1”(LDS、PingFederate、CA)和“Server2”(IIS)。我认为我可能会遇到问题,因为我在两个机器之间没有设置 SSL,所以我昨天花了半天时间为两台机器设置 CA 并创建证书。我相当确定它正在工作,因为我在错误日志中不再看到任何错误,并且我可以使用 LDP 使用端口 636 并检查 SSL 登录到 LDS。我还应该提到这些机器并不在域环境中。我已经编辑了测试网络上所有机器上的主机文件。
我尝试了不同的代码变体:
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();例外情况是“登录失败:未知的用户名或错误的密码”。
如果我确实尝试使用 AuthenticatioTypes.None 在端口 389 下运行此代码 | AuthenticationTypes.FastBind,它将在 de.Invoke("ChangePassword", new object[] { pwd, newPwd }); 处失败;但“未知名称”除外。我真的很想让它在 SSL 下运行,或者至少不以明文形式传输任何密码。我的网站确实通过 HTTPS 运行。我确实尝试修改 LDS 上的 dsHeuristics 值,以便可以通过非 SSL 连接更改密码,但这也不起作用。
任何人可能提出的任何建议将不胜感激。
I have been searching the internet for days trying to solve this problem.
I am working on a project where I have a requirement of allowing the user to change their password using an ASP.NET web application.
I must use "ChangePassword" and not "SetPassword" since I must enforce password history, and not allow any users in the LDS any more privileges than they need. I am trying to complete this task on a dev environment. I have two machines "Server1" (LDS, PingFederate, CA), and "Server2" (IIS). I thought I might be running into problems because I did not have SSL setup between the two boxes, so I spent half the day yesterday setting up a CA and creating certificates for both machines. I am fairly certain it is working since I am no longer seeing any errors in the error log, and I can login to the LDS using LDP using port 636 with SSL checked. I should also mention that these machines are not in a domain environment. I have edited the hosts file on all machines on the test network.
I have tried different variations of code:
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;
}
I get an exception on the first version at Object obj = de.NativeObject;. I was using this to determine if a bind was happening correctly, and was inserted as a debugging step since this is how I was authenticating a user over port 389. The exception is "Logon failure: unknown user name or bad password."
I get an exception on the second version at de.Options.PasswordEncoding = PasswordEncodingMethod.PasswordEncodingSsl; The exception is "Logon failure: unknown user name or bad password."
I get an exception on the third version at SearchResult sr = ds.FindOne(); The exception is "Logon failure: unknown user name or bad password."
If I do attempt to run this code under port 389 with AuthenticatioTypes.None | AuthenticationTypes.FastBind, it will fail at de.Invoke("ChangePassword", new object[] { pwd, newPwd }); with the exception "Unknown Name". I would really like to get this running under SSL or at least not transmit any passwords in the clear. I do have the site running over HTTPS. I did try modifying the dsHeuristics value on the LDS so that I could do password changes over a non-SSL connection, but that did not work either.
Any suggestions that anybody might have would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我终于能够成功更改密码了。我使用了 http://www.informit.com 上提供的信息/articles/article.aspx?p=474649&seqNum=4
我使用了这三个函数:
我从允许更改密码的页面后面的代码中像这样调用了该函数:
I was able to finally get the password change working. I used the information presented on http://www.informit.com/articles/article.aspx?p=474649&seqNum=4
I used these three functions:
I called the function like so from the code behind of the page that allows password changes: