2011-07-29 51 views
2

我們擁有一個Forms Authenticated Intranet,它爲登錄查詢AD並在會話中存儲Windows身份的副本,以便稍後在更新用戶時模擬用戶AD入口。我們不能使用Windows身份驗證(長篇故事)。模擬更新ASP.NET窗體身份驗證站點中的用戶AD信息

所以登錄代碼:

[DllImport("advapi32.dll")] 
     public static extern bool LogonUser(String 
      lpszUsername, String lpszDomain, 
      String lpszPassword, int dwLogonType, int 
       dwLogonProvider, out int phToken); 

     public bool LoginWindowsUser(String domain, String username, String pwd, HttpSessionStateBase session) 
     { 

      int ret = 0; 
      int l_token1; 
      bool loggedOn = LogonUser(username, 
       domain, pwd, 
       // Logon type=LOGON32_LOGON_NETWORK_CLEARTEXT. 
      3, 
       // Logon provider=LOGON32_PROVIDER_DEFAULT. 
      0, 
       // User token for specified user is returned 
       //here. 
      out l_token1); 

      if (loggedOn) 
      { 
       IntPtr token2 = new IntPtr(l_token1); 
       var l_Wid = new WindowsIdentity(token2); 


       session["WindowsIdentity"] = l_Wid; 
      } 
      return loggedOn; 
     } 

再後來,當我們需要更新用戶的AD信息,我們這樣做:

public void UpdateUserProperty(string username, string propertyName, string propertyValue) 
     { 
      // Obtain the authenticated user's identity. 
      var winId = (WindowsIdentity) ControllerContext.HttpContext.Session["WindowsIdentity"]; 
      // Start impersonating. 
      using (WindowsImpersonationContext ctx = winId.Impersonate()) 
      { 
       try 
       { 
        var ds = new DirectorySearcher(); 
        int ind = username.IndexOf("\\") + 1; 
        username = username.Substring(ind, username.Length - ind); 

        var filter = "(&(objectCategory=Person)(objectClass=user)"; 

        if (!username.IsNullOrEmpty()) 
        { 
         filter += "(samaccountname=*{0}*)".F(username); 
        } 

        filter += ")"; 

        ds.Filter = filter; 

        foreach (var property in ADUserDetailsDisplay.LoadProperties()) 
        { 
         ds.PropertiesToLoad.Add(property); 
        } 

      ///////////// ERROR OCCURS AFTER NEXT LINE ///////////// 

        var searchResult = ds.FindOne(); 

        var userDirectoryEntry = searchResult.GetDirectoryEntry(); 

        if (propertyValue.IsNullOrEmpty()) 
        { 
         if (userDirectoryEntry.Properties[propertyName].Count > 0) userDirectoryEntry.Properties[propertyName].RemoveAt(0); 
        } 
        else if (userDirectoryEntry.Properties[propertyName].Count == 0) 
        { 
         userDirectoryEntry.Properties[propertyName].Add(propertyValue); 
        } 
        else 
        { 
         userDirectoryEntry.Properties[propertyName][0] = propertyValue; 
        } 
        userDirectoryEntry.CommitChanges(); 


       } 
       catch (Exception ex) 
       { 
        TempData.AddErrorMessage("Unable to update user: " + ex.Message); 
       } 
       finally 
       { 
        // Revert impersonation. 
        if (ctx != null) 
         ctx.Undo(); 
       } 
      } 
      // Back to running under the default ASP.NET process identity. 

     } 

的問題是,我們得到以下錯誤:

無法更新用戶:發生操作錯誤。

如果有人能指導我解決問題,我將非常感激。

使用IIS 7.5 Win2008 R2 ASP.NET MVC2

謝謝。

回答

0

您的上下文/ searchroot在哪裏告訴它您嘗試連接到哪個/您嘗試搜索的位置?

Ex。

// Bind to the users container. 
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=users,DC=fabrikam,DC=com"); 
// Create a DirectorySearcher object. 
DirectorySearcher mySearcher = new DirectorySearcher(entry); 

如果沒有這個再根據MSDN做SearchRoot的默認值是空... MSDN鏈接:http://msdn.microsoft.com/en-us/library/h9zyssd8.aspx

+0

這不是完整的答案,但導致我找到一個。我最終做的是根據用戶的帳戶創建一個目錄條目,並將我的搜索者綁定到該條目。我使用模擬窗口上下文進行了報廢。 – Richard

0

與AD處理有時是PIA。

無論如何,請確保運行應用程序的應用程序池中設置的帳戶具有活動目錄的管理權限,以便在用戶帳戶中執行更改。

+0

沒有,但是這是一點。我冒充登錄用戶(誰有權更改他們自己的AD信息 - 選定的字段,如電話和地址) – Richard