天天看點

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

閱讀目錄

  • 開始
  • 認識ASP.NET Windows身份認證
  • 通路 Active Directory
  • 在ASP.NET中通路Active Directory
  • 使用Active Directory驗證使用者身份
  • 安全上下文與使用者模拟
  • 在IIS中配置Windows身份認證
  • 關于浏覽器的登入對話框問題
  • 在用戶端代碼中通路Windows身份認證的頁面

上篇部落格我談到了一些關于ASP.NET Forms身份認證方面的話題,這次的部落格将主要介紹ASP.NET Windows身份認證。

Forms身份認證雖然使用廣泛,不過,如果是在 Windows Active Directory 的環境中使用ASP.NET, 那麼使用Windows身份認證也會比較友善。 友善性表現為:我們不用再設計登入頁面,不用編寫登入驗證邏輯。而且使用Windows身份認證會有更好的安全保障。

認識ASP.NET Windows身份認證

要使用Windows身份認證模式,需要在web.config設定:

<authentication mode="Windows" />

      

Windows身份認證做為ASP.NET的預設認證方式,與Forms身份認證在許多基礎方面是一樣的。 上篇部落格我說過:我認為ASP.NET的身份認證的最核心部分其實就是HttpContext.User這個屬性所指向的對象。 在接下來的部分,我将着重分析這個對象在二種身份認證中有什麼差别。

在ASP.NET身份認證過程中,IPrincipal和IIdentity這二個接口有着非常重要的作用。 前者定義使用者對象的基本功能,後者定義辨別對象的基本功能, 不同的身份認證方式得到的這二個接口的執行個體也是不同的。

ASP.NET Windows身份認證是由WindowsAuthenticationModule實作的。 WindowsAuthenticationModule在ASP.NET管線的AuthenticateRequest事件中, 使用從IIS傳遞到ASP.NET的Windows通路令牌(Token)建立一個WindowsIdentity對象,Token通過調用context.WorkerRequest.GetUserToken()獲得, 然後再根據WindowsIdentity 對象建立WindowsPrincipal對象, 然後把它指派給HttpContext.User。

在Forms身份認證中,我們需要建立登入頁面,讓使用者送出使用者名和密碼,然後檢查使用者名和密碼的正确性, 接下來建立一個包含FormsAuthenticationTicket對象的登入Cookie供後續請求使用。 FormsAuthenticationModule在ASP.NET管線的AuthenticateRequest事件中, 解析登入Cookie并建立一個包含FormsIdentity的GenericPrincipal對象, 然後把它指派給HttpContext.User。

上面二段話簡單了概括了二種身份認證方式的工作方式。

我們可以發現它們存在以下差别:

1. Forms身份認證需要Cookie表示登入狀态,Windows身份認證則依賴于IIS

2. Windows身份認證不需要我們設計登入頁面,不用編寫登入驗證邏輯,是以更容易使用。

在授權階段,UrlAuthorizationModule仍然會根據目前使用者檢查将要通路的資源是否得到許可。 接下來,FileAuthorizationModule檢查 HttpContext.User.Identity 屬性中的 IIdentity 對象是否是 WindowsIdentity 類的一個執行個體。 如果 IIdentity 對象不是 WindowsIdentity 類的一個執行個體,則 FileAuthorizationModule 類停止處理。 如果存在 WindowsIdentity 類的一個執行個體,則 FileAuthorizationModule 類調用 AccessCheck Win32 函數(通過 P/Invoke) 來确定是否授權經過身份驗證的用戶端通路請求的檔案。 如果該檔案的安全描述符的随機通路控制清單 (DACL) 中至少包含一個 Read 通路控制項 (ACE),則允許該請求繼續。 否則,FileAuthorizationModule 類調用 HttpApplication.CompleteRequest 方法并将狀态碼 401 傳回到用戶端。

在Windows身份認證中,驗證工作主要是由IIS實作的,WindowsAuthenticationModule其實隻是負責建立WindowsPrincipal和WindowsIdentity而已。 順便介紹一下:Windows 身份驗證又分為“NTLM 身份驗證”和“Kerberos v5 身份驗證”二種, 關于這二種Windows身份認證的更多說明可檢視MSDN技術文章:解釋:ASP.NET 2.0 中的 Windows 身份驗證。 在我看來,IIS最終使用哪種Windows身份認證方式并不影響我們的開發過程,是以本文不會讨論這個話題。

根據我的實際經驗來看,使用Windows身份認證時,主要的開發工作将是根據登入名從Active Directory擷取使用者資訊。 因為,此時不需要我們再設計登入過程,IIS與ASP.NET已經為我們準備好了WindowsPrincipal和WindowsIdentity這二個與使用者身份相關的對象。

回到頂部

通路 Active Directory

我們通常使用LDAP協定來通路Active Directory, 在.net framework中提供了DirectoryEntry和DirectorySearcher這二個類型讓我們可以友善地從托管代碼中通路 Active Directory 域服務。

如果我們要在"test.corp”這個域中搜尋某個使用者資訊,我們可以使用下面的語句構造一個DirectoryEntry對象:

DirectoryEntry entry = new DirectoryEntry("LDAP://test.corp");

      

在這段代碼中,我采用寫死的方式把域名寫進了代碼。

我們如何知道目前電腦所使用的是哪個域名呢?

答案是:檢視“我的電腦”的屬性對話框:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

注意:這個域名不一定與System.Environment.UserDomainName相同。

除了可以檢視“我的電腦”的屬性對話框外,我們還可以使用代碼的方式擷取目前電腦所使用的域名:

private static string GetDomainName()
{
    // 注意:這段代碼需要在Windows XP及較新版本的作業系統中才能正常運作。
    SelectQuery query = new SelectQuery("Win32_ComputerSystem");
    using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {
        foreach( ManagementObject mo in searcher.Get() ) {
            if( (bool)mo["partofdomain"] )
                return mo["domain"].ToString();
        }
    }
    return null;
}
      

當構造了DirectorySearcher對象後,我們便可以使用DirectorySearcher來執行對Active Directory的搜尋。

我們可以使用下面的步驟來執行搜尋:

1. 設定 DirectorySearcher.Filter 訓示LDAP格式篩選器,這是一個字元串。

2. 多次調用PropertiesToLoad.Add() 設定搜尋過程中要檢索的屬性清單。

3. 調用FindOne() 方法擷取搜尋結果。

下面的代碼示範了如何從Active Directory中搜尋登入名為“fl45”的使用者資訊:

static void Main(string[] args)
{
    Console.WriteLine(Environment.UserDomainName);
    Console.WriteLine(Environment.UserName);
    Console.WriteLine("------------------------------------------------");

    ShowUserInfo("fl45", GetDomainName());
}

private static string AllProperties = "name,givenName,samaccountname,mail";

public static void ShowUserInfo(string loginName, string domainName)
{
    if( string.IsNullOrEmpty(loginName) || string.IsNullOrEmpty(domainName) )
        return;

    string[] properties = AllProperties.Split(new char[] { '\r', '\n', ',' }, 
                        StringSplitOptions.RemoveEmptyEntries);

    try {
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName);
        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = "(samaccountname=" + loginName + ")";

        foreach( string p in properties )
            search.PropertiesToLoad.Add(p);

        SearchResult result = search.FindOne();

        if( result != null ) {
            foreach( string p in properties ) {
                ResultPropertyValueCollection collection = result.Properties[p];
                for( int i = 0; i < collection.Count; i++ )
                    Console.WriteLine(p + ": " + collection[i]);
            }
        }
    }
    catch( Exception ex ) {
        Console.WriteLine(ex.ToString());
    }
}
      

結果如下:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

在前面的代碼,我在搜尋Active Directory時,隻搜尋了"name,givenName,samaccountname,mail"這4個屬性。 然而,LDAP還支援更多的屬性,我們可以使用下面的代碼檢視更多的使用者資訊: 

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

回到頂部

在ASP.NET中通路Active Directory

前面我在一個控制台程式中示範了通路Active Directory的方法,通過示例我們可以看到:在代碼中,我用Environment.UserName就可以得到目前使用者的登入名。 然而,如果是在ASP.NET程式中,通路Environment.UserName就很有可能得不到真正使用者登入名。 因為:Environment.UserName是使用WIN32API中的GetUserName擷取線程相關的使用者名,但ASP.NET運作在IIS中,線程相關的使用者名就不一定是用戶端的使用者名了。 不過,ASP.NET可以模拟使用者方式運作,通過這種方式才可以得到正确的結果。關于“模拟”的話題在本文的後面部分有說明。

在ASP.NET中,為了能可靠的擷取登入使用者的登入名,我們可以使用下面的代碼:

/// <summary>
/// 根據指定的HttpContext對象,擷取登入名。
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static string GetUserLoginName(HttpContext context)
{
    if( context == null )
        return null;

    if( context.Request.IsAuthenticated == false )
        return null;

    string userName = context.User.Identity.Name;
    // 此時userName的格式為:UserDomainName\LoginName
    // 我們隻需要後面的LoginName就可以了。

    string[] array = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
    if( array.Length == 2 )
        return array[1];

    return null;
}
      

在ASP.NET中使用Windows身份認證時,IIS和WindowsAuthenticationModule已經做了許多驗證使用者的相關工作, 雖然我們可以使用前面的代碼擷取到使用者的登入名,但使用者的其它資訊即需要我們自己來擷取。 在實際使用Windows身份認證時,我們要做的事:基本上就是從Active Directory中根據使用者的登入名擷取所需的各種資訊。

比如:我的程式在運作時,還需要使用以下與使用者相關的資訊:

public sealed class UserInfo
{
    public string GivenName;
    public string FullName;
    public string Email;
}

      

那麼,我們可以使用這樣的代碼來擷取所需的使用者資訊: 

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

使用UserHelper的頁面代碼:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>WindowsAuthentication DEMO  - http://www.cnblogs.com/fish-li/</title>
</head>
<body>
<% if( Request.IsAuthenticated ) { %>
    目前登入全名:<%= Context.User.Identity.Name.HtmlEncode()%> <br />
    
    <% var user = UserHelper.GetCurrentUserInfo(Context); %>
    <% if( user != null ) { %>
        使用者短名:<%= user.GivenName.HtmlEncode()%> <br />
        使用者全名:<%= user.FullName.HtmlEncode() %> <br />
        郵箱位址:<%= user.Email.HtmlEncode() %>
    <% } %>    
<% } else { %>
    目前使用者還未登入。
<% } %>
</body>
</html>

      

程式運作的效果如下:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

另外,還可以從Active Directory查詢一個叫做memberof的屬性(它與Windows使用者組無關),有時候可以用它區分使用者,設計與權限相關的操作。

在設計資料持久化的表結構時,由于此時沒有“使用者表”,那麼我們可以直接儲存使用者的登入名。 剩下的開發工作就與Forms身份認證沒有太多的差别了。

回到頂部

使用Active Directory驗證使用者身份

前面介紹了ASP.NET Windows身份認證,在這種方式下,IIS和WindowsAuthenticationModule為我們實作了使用者身份認證的過程。 然而,有時可能由于各種原因,需要我們以程式設計的方式使用Active Directory驗證使用者身份,比如:在WinForm程式,或者其它的驗證邏輯。

我們不僅可以從Active Directory中查詢使用者資訊,也可以用它來實作驗證使用者身份,這樣便可以實作自己的登入驗證邏輯。

不管是如何使用Active Directory,我們都需要使用DirectoryEntry和DirectorySearcher這二個對象。 DirectoryEntry還提供一個構造函數可讓我們輸入使用者名和密碼:

// 摘要:
//     初始化 System.DirectoryServices.DirectoryEntry 類的新執行個體。
//
// 參數:
//   Password:
//     在對用戶端進行身份驗證時使用的密碼。DirectoryEntry.Password 屬性初始化為該值。
//
//   username:
//     在對用戶端進行身份驗證時使用的使用者名。DirectoryEntry.Username 屬性初始化為該值。
//
//   Path:
//     此 DirectoryEntry 的路徑。DirectoryEntry.Path 屬性初始化為該值。
public DirectoryEntry(string path, string username, string password);

      

要實作自己的登入檢查,就需要使用這個構造函數。

以下是我寫用WinForm寫的一個登入檢查的示例:

private void btnLogin_Click(object sender, EventArgs e)
{
    if( txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0 ) {
        MessageBox.Show("使用者名或者密碼不能為空。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    string ldapPath = "LDAP://" + GetDomainName();
    string domainAndUsername = Environment.UserDomainName + "\\" + txtUsername.Text;
    DirectoryEntry entry = new DirectoryEntry(ldapPath, domainAndUsername, txtPassword.Text);

    DirectorySearcher search = new DirectorySearcher(entry);

    try {
        SearchResult result = search.FindOne();

        MessageBox.Show("登入成功。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch( Exception ex ) {
        // 如果使用者名或者密碼不正确,也會抛出異常。
        MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop);
    }
}
      

程式運作的效果如下:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

回到頂部

安全上下文與使用者模拟

在ASP.NET Windows身份認證環境中,與使用者相關的安全上下文對象儲存在HttpContext.User屬性中,是一個類型為WindowsPrincipal的對象, 我們還可以通路HttpContext.User.Identity來擷取經過身份認證的使用者辨別,它是一個WindowsIdentity類型的對象。

在.NET Framework中,我們可以通過WindowsIdentity.GetCurrent()擷取與目前線程相關的WindowsIdentity對象, 這種方法擷取的是目前運作的Win32線程的安全上下文辨別。 由于ASP.NET運作在IIS程序中,是以ASP.NET線程的安全辨別其實是從IIS的程序中繼承的, 是以此時用二種方法得到的WindowsIdentity對象其實是不同的。

在Windows作業系統中,許多權限檢查都是基于Win32線程的安全上下文辨別, 于是前面所說的二種WindowsIdentity對象會造成程式設計模型的不一緻問題, 為了解決這個問題,ASP.NET提供了“模拟”功能,允許線程以特定的Windows帳戶的安全上下文來通路資源。

為了能更好的了解模拟的功能,我準備了一個示例(ShowWindowsIdentity.ashx):

public class ShowWindowsIdentity : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        // 要觀察【模拟】的影響,
        // 可以啟用,禁止web.config中的設定:<identity impersonate="true"/>
        
        context.Response.ContentType = "text/plain";

        context.Response.Write(Environment.UserDomainName + "\\" + Environment.UserName + "\r\n");
        
        WindowsPrincipal winPrincipal = (WindowsPrincipal)HttpContext.Current.User;
        context.Response.Write(string.Format("HttpContext.Current.User.Identity: {0}, {1}\r\n", 
                winPrincipal.Identity.AuthenticationType, winPrincipal.Identity.Name));
        
        WindowsPrincipal winPrincipal2 = (WindowsPrincipal)Thread.CurrentPrincipal;
        context.Response.Write(string.Format("Thread.CurrentPrincipal.Identity: {0}, {1}\r\n",
                winPrincipal2.Identity.AuthenticationType, winPrincipal2.Identity.Name));

        WindowsIdentity winId = WindowsIdentity.GetCurrent();
        context.Response.Write(string.Format("WindowsIdentity.GetCurrent(): {0}, {1}",
                winId.AuthenticationType, winId.Name));
    }
      

首先,在web.config中設定:

<authentication mode="Windows" />

      

注意:要把網站部署在IIS中,否則看不出效果。

此時,通路ShowWindowsIdentity.ashx,将看到如下圖所示的結果:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

現在修改一下web.config中設定:(注意:後面加了一句配置)

<authentication mode="Windows" />
<identity impersonate="true"/>

      

此時,通路ShowWindowsIdentity.ashx,将看到如下圖所示的結果:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

說明:

1. FISH-SRV2003是我的計算機名。它在一個沒有域的環境中。

2. fish-li是我的一個Windows帳号的登入名。

3. 網站部署在IIS6中,程序以NETWORK SERVICE帳号運作。

4. 打開網頁時,我輸入的使用者名是fish-li

前面二張圖檔的差異之處其實也就是ASP.NET的“模拟”所發揮的功能。

關于模拟,我想說四點:

1. 在ASP.NET中,我們應該通路HttpContext.User.Identity擷取目前使用者辨別,那麼就不存在問題(此時可以不需要模拟),例如FileAuthorizationModule就是這樣處理的。

2. 模拟隻是在ASP.NET應用程式通路Windows系統資源時需要應用Windows的安全檢查功能才會有用。

3. Forms身份認證也能配置模拟功能,但隻能模拟一個Windows帳戶。

4. 絕大多數情況下是不需要模拟的。

回到頂部

在IIS中配置Windows身份認證

與使用Forms身份認證的程式不同,使用Windows身份認證的程式需要額外的配置步驟。 這個小節将主要介紹在IIS中配置Windows身份認證,我将常用的IIS6和IIS7.5為例分别介紹這些配置。

IIS6的配置 請參考下圖:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

IIS7.5的配置 請參考下圖:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

注意:Windows身份認證是需要安裝的,方法請參考下圖:

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

回到頂部

關于浏覽器的登入對話框問題

當我們用浏覽器通路一個使用Windows身份認證的網站時,浏覽器都會彈出一個對話框(左IE,右Safari):

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

此時,要求我們輸入Windows的登入帳号,然後交給IIS驗證身份。

首次彈出這個對話框很正常:因為程式要驗證使用者的身份。

然而,每次關閉浏覽器下次重新打開頁面時,又會出現此對話框,此時感覺就很不友善了。

雖然有些浏覽器能記住使用者名和密碼,但我發現FireFox,Opera,Chrome仍然會彈出這個對話框,等待我們點選确定, 隻有Safari才不會打擾使用者直接打開網頁。 IE的那個“記住我的密碼”複選框完全是個擺設,它根本不會記住密碼!

是以,我所試過的所有浏覽器中,隻有Safari是最人性化的。

雖然在預設情況下,雖然IE不會記住密碼,每次都需要再次輸入。

不過,IE卻可以支援不提示使用者輸入登入帳号而直接打開網頁, 此時IE将使用使用者的目前Windows登入帳号傳遞給IIS驗證身份。

要讓IE打開一個Windows身份認證的網站不提示登入對話框,必須滿足以下條件:

1. 必須在 IIS 的 Web 站點屬性中啟用 Windows 內建身份驗證。

2. 用戶端和Web伺服器都必須在基于Microsoft Windows的同一個域内。

3. Internet Explorer 必須把所請求的 URL 視為 Intranet(本地)。

4. Internet Explorer 的 Intranet 區域的安全性設定必須設為“隻在 Intranet 區域自動登入”。

5. 請求Web頁的使用者必須具有通路該Web頁以及該Web頁中引用的所有對象的适當的檔案系統(NTFS)權限。

6. 使用者必須用域帳号登入到Windows 。

在這幾個條件中,如果網站是在一個Windows域中運作,除了第3條可能不滿足外,其它條件應該都容易滿足(第4條是預設值)。 是以,要讓IE不提示輸入登入帳号,隻要確定第3條滿足就可以了。 下面的圖檔示範了如何完成這個配置:(注意:配置方法也适合用域名通路的情況)

細說ASP.NET Windows身份認證通路 Active Directory在ASP.NET中通路Active Directory使用Active Directory驗證使用者身份安全上下文與使用者模拟在IIS中配置Windows身份認證關于浏覽器的登入對話框問題在用戶端代碼中通路Windows身份認證的頁面

另外,除了在IE中設定Intranet外,還可以在通路網站時,用計算機名代替IP位址或者域名, 那麼IE始終認為是在通路Intranet内的網站,此時也不會彈出登入對話框。

在此,我想再啰嗦三句:

1. IE在內建Windows身份認證時,雖然不提示登入對話框,但是不表示不安全,它會自動傳遞登入憑據。

2. 這種行為隻有IE才能支援。(其它的浏覽器隻是會記住密碼,在實作上其實是不一樣的。)

3. 內建Windows身份認證,也隻适合在Intranet的環境中使用。

回到頂部

在用戶端代碼中通路Windows身份認證的頁面

在上篇部落格中,我示範了如何用代碼通路一個使用Forms身份認證的網站中的受限頁面,方法是使用CookieContainer對象接收服務端生的登入Cookie。 然而,在Windows身份認證的網站中,身份驗證的過程發生在IIS中,而且根本不使用Cookie儲存登入狀态,而是需要在請求時發送必要的身份驗證資訊。

在使用代碼做為用戶端通路Web伺服器時,我們仍然需要使用HttpWebRequest對象。 為了能讓HttpWebRequest在通路IIS時發送必要的身份驗證資訊,HttpWebRequest提供二個屬性都可以完成這個功能:

// 擷取或設定請求的身份驗證資訊。
//
// 傳回結果:
//     包含與該請求關聯的身份驗證憑據的 System.Net.ICredentials。預設為 null。
public override ICredentials Credentials { get; set; }


// 擷取或設定一個 System.Boolean 值,該值控制預設憑據是否随請求一起發送。
//
// 傳回結果:
//     如果使用預設憑據,則為 true;否則為 false。預設值為 false。
public override bool UseDefaultCredentials { get; set; }
      

下面是我準備的完整的示例代碼(注意代碼中的注釋):

static void Main(string[] args)
{
    try {
        // 請把WindowsAuthWebSite1這個網站部署在IIS中,
        // 開啟Windows認證方式,并禁止匿名使用者通路。
        // 然後修改下面的通路位址。
        HttpWebRequest request = 
            (HttpWebRequest)WebRequest.Create("http://localhost:33445/Default.aspx");

        // 下面三行代碼,啟用任意一行都是可以的。
        request.UseDefaultCredentials = true;
        //request.Credentials = CredentialCache.DefaultCredentials;
        //request.Credentials = CredentialCache.DefaultNetworkCredentials;
        // 如果上面的三行代碼全被注釋了,那麼将會看到401的異常資訊。

        using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) {
            using( StreamReader sr = new StreamReader(response.GetResponseStream()) ) {
                Console.WriteLine(sr.ReadToEnd());
            }
        }
    }
    catch( WebException wex ) {
        Console.WriteLine("=====================================");
        Console.WriteLine("異常發生了。");
        Console.WriteLine("=====================================");
        Console.WriteLine(wex.Message);
    }
}
      

其實關鍵部分還是設定UseDefaultCredentials或者Credentials,代碼中的三種方法是有效的。

這三種方法的差别:

1. Credentials = CredentialCache.DefaultCredentials; 表示在發送請求會帶上目前使用者的身份驗證憑據。

2. UseDefaultCredentials = true; 此方法在内部會調用前面的方法,是以與前面的方法是一樣的。

3. Credentials = CredentialCache.DefaultNetworkCredentials; 是在.NET 2.0中引用的新方法。

關于DefaultCredentials和DefaultNetworkCredentials的更多差别,請看我整理的表格:

Credentials屬性 申明類型 執行個體類型 .NET支援版本
DefaultCredentials ICredentials SystemNetworkCredential 從1.0開始
DefaultNetworkCredentials NetworkCredential SystemNetworkCredential 從2.0開始

三個類型的繼承關系:

1. NetworkCredential實作了ICredentials接口,

2. SystemNetworkCredential繼承自NetworkCredential。

在結束這篇部落格之前,我想我應該感謝新蛋。

在新蛋的網絡環境中,讓我學會了使用Windows身份認證。

除了感謝之外,我現在還特别懷念 fl45 這個登入名......

點選此處下載下傳示例代碼

如果,您認為閱讀這篇部落格讓您有些收獲,不妨點選一下右下角的【推薦】按鈕。

如果,您希望更容易地發現我的新部落格,不妨點選一下右下角的【關注 Fish Li】。

因為,我的寫作熱情也離不開您的肯定支援。

感謝您的閱讀,如果您對我的部落格所講述的内容有興趣,請繼續關注我的後續部落格,我是Fish Li 。

轉自:http://www.cnblogs.com/fish-li/archive/2012/05/07/2486840.html#_label1