2012-01-23 61 views
3

我想知道是否有任何.Net方式來驗證Active Directory用戶憑證,即使用戶的密碼已過期或用戶具有「用戶必須在下次登錄時更改密碼」設置。 我已經嘗試了PrincipalContext.ValidateCredential,並且這會爲我的用戶返回false。我也嘗試過Ldap Bind,那也不管用。 我的目的是對用戶進行身份驗證,如果密碼已過期,或者他必須在下次登錄時更改密碼,那麼請使用更改密碼對話框提示他。如何在用戶密碼過期時檢查AD用戶憑證或「用戶必須在下次登錄時更改密碼」

+1

如果你需要檢查一個過期的密碼,那麼它聽起來像你在做一些錯誤的事情。我相信,密碼過期的一點是它不能再使用,不應該用於認證。也許你不想過於熱情地等待密碼或類似的東西? – Chris

+1

我正在開發一個UI,用於驗證用戶身份,然後在密碼過期或在下次登錄時更改密碼時提示他更改密碼。如果我只在第一步驗證用戶的存在,那麼用戶體驗就會令人困惑。用戶似乎在第一個屏幕上登錄,然後當他嘗試更改密碼時(通過輸入舊密碼和新密碼),他會發現他的舊密碼不正確。 Windows在密碼過期時也是如此,除非您提供了正確的密碼,否則您無法進入更改密碼屏幕。 – Monica

+0

我已經嘗試過並且沒有工作:LDap綁定,UserPrincipal.ValidateCredentials,LogonUser(這隻適用於本地機器)。 – Monica

回答

0

This article可能會有所幫助。您可以使用DirectorySearcher來確定用戶是否存在以及密碼狀態是什麼。

+0

我需要驗證用戶的密碼是否正確(即使它已過期或用戶必須在下次登錄時更改密碼)。只是勉強用戶存在,並獲得密碼狀態是不夠的:( – Monica

+0

嘿莫妮卡,你有沒有解決這個問題?我也遇到一種情況,我不只是想調用UserPrincipal.SetPassword(newPassword )方法,我需要一個像UserPrincipal.SetPassword(oldPassword,newPassword)重載,在設置新的重載之前檢查舊的信譽。 – Pedro

6

我們有幾個AD控制器在我們的設置,在Windows上PrincipalContext.ValidateCredentials方法將總是在AD控制器返回false上的用戶2003服務器與「用戶下次登錄時須更改密碼」複選框選中。

但是對於Windows 2008 R2服務器上的服務器,如果即使複選框被選中,信用有效也會返回true。

所以,我只是確保我的代碼是擊中了Windows 2008 R2服務器之一,並做了訣竅。

我沒有爲2003服務器的解決方案工作(在我意識到事情會在其他人的工作之前)。下面是代碼:

var adContext = new PrincipalContext(ContextType.Domain, adLocation, adContainer, adAdminUsername, adAdminPassword); 

var initialValidation = adContext.ValidateCredentials(username, password); 
Console.WriteLine("Initial validation returned: " + initialValidation); 

if (!initialValidation) 
{ 
    // maybe validation failed because "user must change password at next logon". 
    // let's see if that is the case. 

    var user = UserPrincipal.FindByIdentity(adContext, username); 
    if (user.LastPasswordSet == null) 
    { 
     // the user must change his password at next logon. So this might be 
     // why validation returned false 

     // uncheck the "change password" checkbox and attempt validation again 

     var deUser = user.GetUnderlyingObject() as DirectoryEntry; 
     var property = deUser.Properties["pwdLastSet"]; 
     property.Value = -1; 
     deUser.CommitChanges(); 

     // property was unset, retry validation 
     adContext.ValidateCredentials(username, password); 
     Console.WriteLine("Secondary validation returned: " + adContext.ValidateCredentials(username, password)); 

     // re check the checkbox 
     property.Value = 0; 
     deUser.CommitChanges(); 
    } 
} 
+0

設置pwdLastSet爲我解決了問題,謝謝你+ Pedro –

+0

實際上並不那麼簡單。 2008如果它們運行在不同的域功能級別,例如2000,2003或2008 R2,則它們的行爲會有所不同。無論您運行哪種AD版本,都應該更好地檢查這兩種方法。 –

0

我絕對發現沒有辦法驗證用戶是否設置了標誌「用戶必須在下次登錄時更改密碼」。

這是我想出的解決方案。對不起它在VB中,它是繼承代碼:)

 

    ' Authenticate Using the Administrator Account 
    Dim domainAndUserName As String = tmpDomain + "\" + tmpUser 
    Dim entry As DirectoryEntry = New DirectoryEntry(sLDAP_PATH, m_AD_BIND_USERNAME, m_AD_BIND_PASSWORD) 
    Dim ds As DirectorySearcher = New DirectorySearcher(entry) 
    ds.Filter = "(&(objectClass=user)(anr=" + tmpUser + "))" 

    ' Lookup the User 
    Dim user As SearchResult = ds.FindOne() 

    ' Check the User Status 

    ' If the "User must change password at next logon" flag is set 
    ' then we need to clear it before we can test the users credentials     
    If Convert.ToInt64(user.Properties("pwdLastSet").Item(0)) = 0 Then 
     Dim deUser As DirectoryEntry = user.GetDirectoryEntry() 
     deUser.Properties("pwdLastSet")(0) = -1 
     deUser.CommitChanges() 

     Dim isValidCreds As Boolean = True 

     ' Create Directory Entry for User 
     entry = New DirectoryEntry(sLDAP_PATH, domainAndUserName, Password) 

     ' Attempt to create NativeObject based on credentials 
     ' If it fails the credentials are invalid 
     Try 
      Dim obj As Object = entry.NativeObject() 
     Catch ex As Exception 
      isValidCreds = False 
     End Try 

     ' Reset the flag 
     deUser.Properties("pwdLastSet")(0) = 0 
     deUser.CommitChanges() 

     ' If the credentials are valid, return '1907' 
     ' if the credentials aren't valid, return '1326' 
     If isValidCreds Then 
      Throw New Exception("1907") ' Password Expired 
     Else 
      Throw New Exception("1326") ' Invalid Login 
     End If 
    ElseIf Convert.ToInt64(user.Properties("userAccountControl").Item(0)) = 514 Then 
     Throw New Exception("1331") ' Account Disabled 
    ElseIf user.Properties("lockoutTime").Count > 0 AndAlso Convert.ToInt64(user.Properties("lockouttime").Item(0)) > 0 Then 
     Throw New Exception("1909") ' Account Locked Out 
    End If 

唯一要注意的是有對因緩慢的複製,即,可以設置標誌的問題,但由於更新一個不是招潛力當你試圖創建'NativeObject'時,它不會複製到你所有的DC中,它可能仍然會失敗。

相關問題