C# 使用LDAP更改用户密码

C# 使用LDAP更改用户密码,c#,ldap,change-password,C#,Ldap,Change Password,这是我的密码 var fullName = ApplicationSettings.DefaultUser; var userId = fullName.Substring(fullName.LastIndexOf(@"\", StringComparison.Ordinal) + 1).ToUpper(CultureInfo.InvariantCulture); try { DirectoryEntry entry = new DirectoryEntry("

这是我的密码

var fullName = ApplicationSettings.DefaultUser;
var userId = fullName.Substring(fullName.LastIndexOf(@"\", StringComparison.Ordinal) + 1).ToUpper(CultureInfo.InvariantCulture);
    try
    {

        DirectoryEntry entry = new DirectoryEntry("LDAP://ldapaddressstring", userId, existingPassword, AuthenticationTypes.Secure);

        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = "(&(objectClass=user)(sAMAccountName=" + userId + "))";
        entry = search.FindOne().GetDirectoryEntry();
        entry.Invoke("ChangePassword", new object[] { existingPassword, newPassword });
    }
    catch (Exception ex)
    {

        //throw plain exception
        throw ex;      

    }

我收到错误的用户名或密码错误。有什么想法吗?

您希望用户更改自己的密码,还是管理员重置密码

您是否获得了要输入的内容,或者在调用FindOne时发生了错误

这是我使用的代码,“Impersonator”是一个类,允许模拟域管理员帐户以确保适当的权限。你应该能找到它

公共服务响应更改密码(字符串用户名、字符串旧密码、字符串新密码)
{
ServiceResponse=新的ServiceResponse();
尝试
{
var entry=newdirectoryEntry(域用户连接字符串、用户名、旧密码);
var nativeObject=entry.nativeObject;
//检查通过。现在可以重置密码吗
entry=RootDirectoryEntry;
var user=FindUserInDirectoryEntry(用户名,条目);
响应=设置密码(用户,新密码);
user.Close();
}
捕获(DirectoryServicesCOMException ex)
{
response.Status=Status.Error;
response.Message=ex.ExtendedErrorMessage;
m_Logger.Error(“未能更改用户{0}:{1}-{2}”的密码”,用户名,ex.ExtendedErrorMessage,(ex.InnerException??ex));
}
捕获(例外情况除外)
{
response.Status=Status.Error;
response.Message=ex.Message;
m_Logger.Error(“更改用户{0}:{1}-{2}的密码失败”,用户名,例如Message,(例如InnerException??ex));
}
返回响应;
}
/// 
///在目录项中查找用户。
/// 
///用户名。
///dir条目。
/// 
受保护的静态DirectoryEntry FindUserInDirectoryEntry(字符串用户名,DirectoryEntry dirEntry)
{
//盗取域名,如果用户名包含它
string domainName=string.Format(@“{0}\”,domainName.ToLowerInvariant();
username=username.Replace(域名“”);
DirectorySearcher search=新的DirectorySearcher(dirEntry)
{
Filter=String.Format(((samAccountName={0})”,用户名)
};
var searchResult=searcher.FindOne();
if(searchResult!=null)
{
DirectoryEntry user=searchResult.GetDirectoryEntry();
返回用户;
}
返回null;
}
private ServiceResponse设置密码(DirectoryEntry用户,字符串密码)
{
ServiceResponse=新的ServiceResponse();
尝试
{
使用(var模拟程序=新模拟程序(DomainAdminUsername、DomainName、DomainAdminPassword))
{
调用(“SetPassword”,新对象[]{password});
user.Properties[“LockOutTime”].Value=0;//解锁帐户
user.CommitChanges();
}
response.Status=Status.Success;
}
捕获(DirectoryServicesCOMException ex)
{
response.Status=Status.Error;
response.Message=ex.ExtendedErrorMessage;
m_Logger.Error(“用户{0}:{1}的SetPassword失败”,user.Name,ex.ExtendedErrorMessage);
}
捕获(例外情况除外)
{
response.Status=Status.Error;
response.Message=ex.Message;
m_Logger.Error({2}:{3}:{4}处的{1}为用户{0}设置密码失败),user.Name,
DomainAdminUsername、DomainName、,
例如Message,(例如InnerException±ex).ToString();
}
返回响应;
}
可能影响您的注意事项:

  • 删除域名(如果存在)
  • 检索“NativeObject”似乎对缓存/连接有影响
  • 这是使用“设置密码”,需要

  • 谢谢,罗杰。我需要用户能够更改自己的密码,最好没有任何第三方类。这可能吗?我的印象是这样的。是的,你应该能够删除模拟程序(这是免费可用的源代码),并交换到ChangePassword而不是SetPassword。主要问题应该是:例外是哪一行?它可以是您声明/分配条目的位置,也可以是您调用ChangePassword的位置
    public ServiceResponse ChangePassword(string username, string oldPassword, string newPassword)
            {
                ServiceResponse response = new ServiceResponse();
    
                try
                {
                    var entry = new DirectoryEntry(DomainUsersConnectionString, username, oldPassword);
                    var nativeObject = entry.NativeObject;
    
                    // Check passed. Can reset the password now
                    entry = RootDirectoryEntry;
                    var user = FindUserInDirectoryEntry(username, entry);
                    response = SetPassword(user, newPassword);
                    user.Close();
                }
                catch (DirectoryServicesCOMException ex)
                {
                    response.Status = Status.Error;
                    response.Message = ex.ExtendedErrorMessage;
                    m_Logger.Error("Failed to change password for user {0}: {1} - {2}", username, ex.ExtendedErrorMessage, (ex.InnerException ?? ex));
                }
                catch (Exception ex)
                {
                    response.Status = Status.Error;
                    response.Message = ex.Message;
                    m_Logger.Error("Failed to change password for user {0}: {1} -{2}", username, ex.Message, (ex.InnerException ?? ex));
                }
                return response;
            }
    
    
    
            /// <summary>
            /// Finds the user in directory entry.
            /// </summary>
            /// <param name="username">The username.</param>
            /// <param name="dirEntry">The dir entry.</param>
            /// <returns></returns>
            protected static DirectoryEntry FindUserInDirectoryEntry(string username, DirectoryEntry dirEntry)
            {
                // rip off Domain name if username contains it
                string domainName = String.Format(@"{0}\", DomainName).ToLowerInvariant();
                username = username.Replace(domainName, "");
                DirectorySearcher searcher = new DirectorySearcher(dirEntry)
                {
                    Filter = String.Format("(samAccountName={0})", username)
                };
                var searchResult = searcher.FindOne();
                if (searchResult != null)
                {
                    DirectoryEntry user = searchResult.GetDirectoryEntry();
                    return user;
                }
                return null;
            }
    
    
    
            private ServiceResponse SetPassword(DirectoryEntry user, string password)
            {
                ServiceResponse response = new ServiceResponse();
    
                try
                {
                    using (var impersonator = new Impersonator(DomainAdminUsername, DomainName, DomainAdminPassword))
                    {
                        user.Invoke("SetPassword", new object[] { password });
                        user.Properties["LockOutTime"].Value = 0; //unlock account
                        user.CommitChanges();
                    }
                    response.Status = Status.Success;
                }
                catch (DirectoryServicesCOMException ex)
                {
                    response.Status = Status.Error;
                    response.Message = ex.ExtendedErrorMessage;
                    m_Logger.Error("SetPassword failed for user {0}: {1}", user.Name, ex.ExtendedErrorMessage);
                }
                catch (Exception ex)
                {
                    response.Status = Status.Error;
                    response.Message = ex.Message;
                    m_Logger.Error("SetPassword failed for user {0} by {1} at {2}: {3}: {4}", user.Name, 
                        DomainAdminUsername, DomainName,
                        ex.Message, (ex.InnerException ?? ex).ToString());
                }
    
                return response;
            }