區網內的AD帳號驗證

  • 1736
  • 0
  • C#
  • 2014-08-22

區網內的AD帳號驗證

在AD網域的環境下,執行程式需要網域使用者的身份驗證,但是非目前電腦登入的使用者。經由身份驗證來確定使用者的相關使用權限、或是其他動作等。

使用 .NET Framework 3.5 以上,加入參考組件 System.DirectoryServices.AccountManagement,透過 PrinicipalContext 類別內的 ValidateCredentials 方法,就可以來進行簡單的AD身份驗證。

 

ValidateCredentials(String, String)

ValidateCredentials(String, String, ContextOptions)

參數1:要驗證的帳號

參數2:要驗證的密碼

參數3:連結到伺服器時使用的選項,可以設定以位元 OR 運算連結的多個選項。

選項名稱 說明
Negotiate 用戶端是使用 Kerberos 或 NTLM 進行驗證。 未提供使用者名稱和密碼時,帳戶管理 API 會使用發出呼叫之執行緒的安全性內容來繫結至物件,這個安全性內容可能是應用程式在其下執行之使用者帳戶的安全性內容,也可能是發出呼叫的執行緒所代表之用戶端使用者帳戶的安全性內容。
Sealing 資料是使用 Kerberos 加密。

這個旗標只能與 Negotiate 內容選項一起使用,不適用於簡單繫結選項。
SecureSocketLayer 通道是使用 Secure Sockets Layer (SSL) 加密。 Active Directory 需要安裝憑證服務才能支援 SSL。
ServerBind 如果應用程式要繫結至特定伺服器名稱,請在使用網域內容型別時指定這個旗標。
Signing 已驗證資料的完整性。 這個旗標只能與 Negotiate 內容選項一起使用,不適用於簡單繫結選項。
SimpleBind 用戶端是使用基本驗證進行驗證。

注意:如果未以簡單繫結指定 SecureSocketsLayer 選項,通訊可能會以純文字在網際網路上傳送。

未指定時的預設值為:Negotiate | Signing | Sealing 。

 

主要程式碼

/// <summary>
/// AD 帳號驗證
/// </summary>
/// <param name="UserID">登入帳號</param>
/// <param name="UserPwd">登入密碼</param>
/// <param name="DomainName">網域名稱</param>
private bool AccountValidationByAD(string UserID, string UserPwd, string DomainName)
{
    if ((UserID.Trim() == string.Empty) || (UserPwd.Trim() == string.Empty)) return false;
    if ((DomainName.Trim() == string.Empty) && ((!UserID.Contains("@")) && (!UserID.Contains("\\")))) return false;
    UserID = UserID.Trim();
    UserPwd = UserPwd.Trim();
    if (DomainName.Trim() != string.Empty) DomainName = DomainName.Trim();

    string FormatUserID, FormatDomainName;
    if (UserID.Contains("@"))
    {
        FormatUserID = UserID.Split('@')[0];
        FormatDomainName = UserID.Split('@')[1];
    }
    else if (UserID.Contains("\\"))
    {
        FormatUserID = UserID.Split('\\')[1];
        FormatDomainName = UserID.Split('\\')[0];
    }
    else
    {
        FormatUserID = UserID;
        FormatDomainName = DomainName;
    }

    try
    {
        System.DirectoryServices.AccountManagement.PrincipalContext ValidationAD = new System.DirectoryServices.AccountManagement.PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain);
        return ValidationAD.ValidateCredentials(FormatUserID, UserPwd, System.DirectoryServices.AccountManagement.ContextOptions.Negotiate);
    }
    catch
    {
        return false;
    }
}

範本頁面

「登入檢查」程式碼

private void btnCheck_Click(object sender, EventArgs e)
{
    if (AccountValidationByAD(txtUserID.Text.Trim(), txtUserPwd.Text.Trim(), txtDomain.Text.Trim()))
    {
        /* 
         * 身份驗證成功,繼續執行自定程式碼。
         *
         */
    }
    else
    {
        /* 
         * 身份驗證失敗,顯示錯誤訊息。
         *
         */
        MessageBox.Show("登入失敗","錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}

 

帳號、密碼、網域名稱的判斷方式

1. 帳號內含有 @ 或 \ 字元,網域名稱則使用帳號解析過後的網域。

2. 不允許空白密碼的身份驗證。

3. 未輸入網域時,帳號內則必需要含有 @ 或 \ 字元。


程式是運氣與直覺堆砌而成的奇蹟。
若不具備這兩者,不可能以這樣的工時實現這樣的規格。
修改規格是對奇蹟吐槽的褻瀆行為。
而追加修改則是相信奇蹟還會重現的魯莽行動。