Server 2016 AD和IIS Express无法设置用户密码但可以创建用户
Server 2016 AD and IIS Express Cannot Set User Password but Can Create User
由于我的 IDE 不断崩溃,我不得不创建一个虚拟机较少的新开发环境,因此我在同一台服务器上创建了一个带有 AD 和 IIS 的虚拟机。
我在我的旧环境中使用了以下代码:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain,
Environment.GetEnvironmentVariable("DOMAIN"),
Environment.GetEnvironmentVariable("USER_OU"),
Environment.GetEnvironmentVariable("SERVICE_USERNAME"),
Environment.GetEnvironmentVariable("SERVICE_PASSWORD"));
UserPrincipalEx usr = new UserPrincipalEx(ctx);
usr.Name = ticket.FirstName + " " + ticket.LastName;
usr.SamAccountName = ticket.Username;
usr.GivenName = ticket.FirstName;
usr.Surname = ticket.LastName;
usr.DisplayName = ticket.FirstName + " " + ticket.Account.LastName;
usr.UserPrincipalName = ticket.Username + "@" + Environment.GetEnvironmentVariable("DOMAIN");
usr.Enabled = enabled;
try
{
usr.Save();
usr.SetPassword(temppwd);
usr.ExpirePasswordNow();
}
我仍然可以保存用户并且它出现在 AD 中,但是 SetPassword 不再有效:
[IIS EXPRESS] Request started: "POST" https://localhost:5001/create
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
--- End of inner exception stack trace ---
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)
我的服务帐户是域管理员,如果我尝试使用自己的 AD 凭据,我会遇到同样的错误。
我已经厌倦了在 Save() 之前调用 SetPassword() 但它在同一点失败了。
唯一的区别是我在同一台服务器上安装了 AD 和 IIS。 Jetbrains Rider 和 VS2019 都玩腻了。我的项目截止日期越来越近了,我真的被困住了。
None 的用户有 'User Cannot Change Password Set' 而新用户在 'Account Options' 下没有任何选项设置。
SetPassword
设置 unicodePwd
属性。这对何时可以更新有一些限制。 documentation for that 表示:
Windows 2000 operating system servers require that the client have a 128-bit (or better) SSL/TLS-encrypted connection to the DC in order to modify this attribute. On Windows Server 2003 operating system and later, the DC also permits modification of the unicodePwd attribute on a connection protected by 128-bit (or better) Simple Authentication and Security Layer (SASL)-layer encryption instead of SSL/TLS.
默认情况下它应该设置一个安全连接(对我来说是这样),但它可能出于某种原因不能在您的设置中。
您可以将构造函数中的 ContextOptions
对象传递给您的 PrincipalContext
。默认情况下,它会自动设置为 ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing
,这应该是安全的。但是 ContextOptions.Negotiate
使用 "either Kerberos or NTLM",而 ContextOptions.Signing
(加密)依赖于 Kerberos。所以也许它正在退回到 NTLM 并且无法加密。
创建帐户后,您可能可以通过检查这些值来确认这一点:
Console.WriteLine(ctx.Options);
Console.WriteLine(((DirectoryEntry) usr.GetUnderlyingObject()).AuthenticationType);
您要寻找的值是:
Negotiate, Signing, Sealing
Secure, Signing, Sealing
这就是我在 SetPassword
工作时所拥有的。但我不确定如果它回退到 NTLM,它是否真的改变了这些值。有时它会很安静地做这件事。
无论如何,如果没有发生 Kerberos,您可以解决该问题,或者尝试通过 LDAPS(LDAP over SSL)进行连接。看起来像这样:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain,
Environment.GetEnvironmentVariable("DOMAIN") + ":636",
Environment.GetEnvironmentVariable("USER_OU"),
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer,
Environment.GetEnvironmentVariable("SERVICE_USERNAME"),
Environment.GetEnvironmentVariable("SERVICE_PASSWORD"));
但这可能会导致其他问题,因为您的 DC 需要有您信任的证书。
由于我的 IDE 不断崩溃,我不得不创建一个虚拟机较少的新开发环境,因此我在同一台服务器上创建了一个带有 AD 和 IIS 的虚拟机。
我在我的旧环境中使用了以下代码:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain,
Environment.GetEnvironmentVariable("DOMAIN"),
Environment.GetEnvironmentVariable("USER_OU"),
Environment.GetEnvironmentVariable("SERVICE_USERNAME"),
Environment.GetEnvironmentVariable("SERVICE_PASSWORD"));
UserPrincipalEx usr = new UserPrincipalEx(ctx);
usr.Name = ticket.FirstName + " " + ticket.LastName;
usr.SamAccountName = ticket.Username;
usr.GivenName = ticket.FirstName;
usr.Surname = ticket.LastName;
usr.DisplayName = ticket.FirstName + " " + ticket.Account.LastName;
usr.UserPrincipalName = ticket.Username + "@" + Environment.GetEnvironmentVariable("DOMAIN");
usr.Enabled = enabled;
try
{
usr.Save();
usr.SetPassword(temppwd);
usr.ExpirePasswordNow();
}
我仍然可以保存用户并且它出现在 AD 中,但是 SetPassword 不再有效:
[IIS EXPRESS] Request started: "POST" https://localhost:5001/create
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
--- End of inner exception stack trace ---
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)
我的服务帐户是域管理员,如果我尝试使用自己的 AD 凭据,我会遇到同样的错误。
我已经厌倦了在 Save() 之前调用 SetPassword() 但它在同一点失败了。
唯一的区别是我在同一台服务器上安装了 AD 和 IIS。 Jetbrains Rider 和 VS2019 都玩腻了。我的项目截止日期越来越近了,我真的被困住了。
None 的用户有 'User Cannot Change Password Set' 而新用户在 'Account Options' 下没有任何选项设置。
SetPassword
设置 unicodePwd
属性。这对何时可以更新有一些限制。 documentation for that 表示:
Windows 2000 operating system servers require that the client have a 128-bit (or better) SSL/TLS-encrypted connection to the DC in order to modify this attribute. On Windows Server 2003 operating system and later, the DC also permits modification of the unicodePwd attribute on a connection protected by 128-bit (or better) Simple Authentication and Security Layer (SASL)-layer encryption instead of SSL/TLS.
默认情况下它应该设置一个安全连接(对我来说是这样),但它可能出于某种原因不能在您的设置中。
您可以将构造函数中的 ContextOptions
对象传递给您的 PrincipalContext
。默认情况下,它会自动设置为 ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing
,这应该是安全的。但是 ContextOptions.Negotiate
使用 "either Kerberos or NTLM",而 ContextOptions.Signing
(加密)依赖于 Kerberos。所以也许它正在退回到 NTLM 并且无法加密。
创建帐户后,您可能可以通过检查这些值来确认这一点:
Console.WriteLine(ctx.Options);
Console.WriteLine(((DirectoryEntry) usr.GetUnderlyingObject()).AuthenticationType);
您要寻找的值是:
Negotiate, Signing, Sealing
Secure, Signing, Sealing
这就是我在 SetPassword
工作时所拥有的。但我不确定如果它回退到 NTLM,它是否真的改变了这些值。有时它会很安静地做这件事。
无论如何,如果没有发生 Kerberos,您可以解决该问题,或者尝试通过 LDAPS(LDAP over SSL)进行连接。看起来像这样:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain,
Environment.GetEnvironmentVariable("DOMAIN") + ":636",
Environment.GetEnvironmentVariable("USER_OU"),
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer,
Environment.GetEnvironmentVariable("SERVICE_USERNAME"),
Environment.GetEnvironmentVariable("SERVICE_PASSWORD"));
但这可能会导致其他问题,因为您的 DC 需要有您信任的证书。