tl;dr
私たちの場合、これはランダムに発生し始めました。これは、自己署名 SSL 証明書の有効期限が切れたためです。IIS で新しいものを作成した後、問題は解決しました。
説明
このスレッドは私を原因に導きます。
SetPassword
なぜそれが必要なのかがわかるように、ここで何をするのかを簡単に要約します。その特定の ADSI メソッドは、実際には 3 つのメソッドをカバーの下にバンドルしています。最初に、LDAP を使用して安全な SSL チャネルを介してパスワードを設定しようとします。次に、Kerberos set password プロトコルを使用して設定を試みます。最後に、 を使用NetUserSetInfo
して設定を試みます。
主な問題は、最初の 2 つの方法のみが、一般に .xml ファイルに入力した資格情報を尊重することですDirectoryEntry
。 たとえば、適切な資格情報と SSL チャネルを提供すると、LDAP パスワード変更メカニズムはそれらの資格情報で機能します...
NetUserSetInfo メソッドを確認すると、認証用のユーザー名/パスワードを入力する場所がないことがわかります。つまり、アンマネージ スレッドのセキュリティ コンテキストしか使用できません。つまり、機能させるには、最初にプログラムで提供したユーザー名とパスワードの組み合わせを偽装する必要があります...
LDAP over SSL は明らかに最善の方法であり (そして私たちが使用していた方法でした)、自己署名 SSL 証明書の有効期限が切れると、Kerberos をスキップして にフォールバックしNetUserSetInfo
、失敗したようです (説明を歓迎します)。私たちが提供した資格情報を使用していなかったためです。(または、投稿者がKerberosに渡された資格情報を見たことがないと言ったため、Kerberosで失敗しただけです)
そのため、新しい自己署名証明書 ( 用COMPUTER.DOMAIN.local
) を作成した後、問題は解決されました。
コードは次のとおりです(誰かが探している場合に備えて):
DirectoryEntry myDE = new DirectoryEntry(@"LDAP://OU=GroupName,DC=DOMAIN,DC=local");
myDE.Username = "administrator";
myDE.Password = "adminPassword";
DirectoryEntries myEntries = myDE.Children;
DirectoryEntry myDEUser = myEntries.Find("CN=UserName");
myDEUser.Invoke("SetPassword", new object[] { "NewPassword" });
myDEUser.Properties["LockOutTime"].Value = 0;
// the following 2 lines are free =)
myDEUser.Properties["userAccountControl"].Value = (int)myDEUser.Properties["userAccountControl"].Value | 0x10000; // don't expire password
myDEUser.Properties["userAccountControl"].Value = (int)myDEUser.Properties["userAccountControl"].Value & ~0x0002; // ensure account is enabled
myDEUser.CommitChanges();