我可以使用System.DirectoryServices.AccountManagement成功设置用户密码,使用:
using (var up = new UserPrincipal(principalContext))
{
up.SetPassword(password);
}
但是,当我从Azure网站执行相同的代码时,它会抛出UnauthorizedAccessException
说Access is denied.
。这是堆栈跟踪:
at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
at System.DirectoryServices.AccountManagement.SDSUtils.SetPassword(DirectoryEntry de, String newPassword)
at System.DirectoryServices.AccountManagement.ADStoreCtx.SetPassword(AuthenticablePrincipal p, String newPassword)
at System.DirectoryServices.AccountManagement.PasswordInfo.SetPassword(String newPassword)
at System.DirectoryServices.AccountManagement.AuthenticablePrincipal.SetPassword(String newPassword)
at Cdp.ServiceBus.Adapters.ActiveDirectoryAdapter.CreateUser(String username, String password) in C:\agent\_work\a1b9797a\CDP\src\Cdp.ServiceBus.Adapters\ActiveDirectoryAdapter.cs:line 46
Active Directory实例正在Azure VM上运行。该网站连接到同一个虚拟网络。在本地开发时,我使用VPN连接到同一个虚拟网络。
使用ContextType.Domain
和ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing
设置principalContext。我还指定虚拟网络的IP地址作为上下文的名称(主机)。此上下文的用户名和密码是AD VM中的管理员。
查看AD VM的安全日志,我可以看到,在本地开发时,会创建一个日志条目,因为我登录的管理员正在尝试重置密码。在Azure上时,不会创建此类日志条目。从这一点我想我可以得出结论,从来没有接到电话。没有其他日志条目向我提供它拥有的信息和/或无法处理它。
我最好的猜测是Azure不允许执行SetPassword API。这可以解释相当低级的UnauthorizedAccessException
。你觉得怎么样?
编辑:
SDSUtils.SetPassword
的签名是:
[SecurityCritical]
internal static void SetPassword(DirectoryEntry de, string newPassword)
是否允许Azure运行归因于SecurityCritical
的代码?
答案 0 :(得分:0)
我对此工作了一段时间,我想我已经明白了。为了使其工作,底层连接必须是安全的:
PrincipalContext _pc = new PrincipalContext(ContextType.Domain, "FQDN", null, ContextOptions.SecureSocketLayer | ContextOptions.Negotiate, _svsUser, _svsPwd);
UserPrincipal _up = UserPrincipal.FindByIdentity(_pc, IdentityType.SamAccountName, usernameToChange);
_up.SetPassword(newPassword);
_up.Save();
注意构造函数调用中的ConextOptions.SecureSocketLayer | ContextOptions.Negotiate
。一旦我在DC上添加了这个并配置了SSL,它就开始工作了。