2013-05-15 111 views
2

我有一個MVC 4應用程序,允許用戶通過密碼重置功能頁面更改其Active Directory密碼。我有以下的代碼,設置新的密碼:設置ASP.Net權限 - 訪問被拒絕。 (異常來自HRESULT:0x80070005(E_ACCESSDENIED))

DirectoryEntry de = sr.GetDirectoryEntry(); 
de.Invoke("SetPassword", new object[] { newPassword }); 
de.Properties["LockOutTime"].Value = 0; 

在嘗試與我有寫入應用程序事件日誌中的錯誤新密碼的詳細信息提交表單:

0x80070005 (E_ACCESSDENIED)) 

我已經將應用程序池的Identity屬性設置爲NetworkService,並認爲這將解決連接問題。還有什麼我需要確保,以便我的ASPNET應用程序可以連接到AD。

+0

是否NetworkService帳戶已經進入AD結構,特別是,這個人的許可? –

+0

我已經使用ASP Impersonate true並且使用了一個完全擁有AD結構權限的帳戶,但是我仍然遇到了這個ACCESS_DENIED錯誤 – Jay

+0

這是一個最近在我們的服務器上突然出現的問題,沒有明顯的催化劑(沒有Windows更新,IIS更改或影響此功能的代碼更改) – snumpy

回答

1

TL;博士

在我們的例子中,這個開始隨機發生。原因是我們的自簽名SSL證書已過期。在IIS中創建一個新問題後,問題已解決。

說明

This thread導致我的原因。

我會簡要回顧一下SetPassword在這裏做什麼,這樣你就可以看到爲什麼你需要它。這個特定的ADSI方法真正捆綁了3種方法。它首先嚐試使用LDAP在安全SSL通道上設置密碼。接下來,它嘗試使用Kerberos設置密碼協議進行設置。最後,它使用NetUserSetInfo來嘗試設置它。

主要問題是隻有前兩種方法通常會尊重您放在DirectoryEntry上的憑據。 如果您提供正確的憑據和實例的SSL通道,在LDAP修改密碼機制將使用這些憑據工作...

如果檢查NetUserSetInfo方法,你會發現沒有地方放一個用戶名/授權密碼。換句話說,它只能使用非託管線程的安全上下文。這意味着,爲了爲它工作,它會模仿你提供編程第一的用戶名/密碼組合...

SSL上的LDAP是顯然是最好的方式去(而且是方法,我們(看起來很受歡迎),一旦我們的自簽名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(); 
相關問題