ASP.NET Web API身份驗證和授權


英語原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

本文是作者所理解和翻譯的內容。

這篇文章包括兩部分:身份驗證和授權。

  • 身份驗證用來確定一個用戶的身份。例如,Alice用她的用戶名和密碼登陸系統,服務器用她的用戶名和密碼來確定她的身份。
  • 授權是判斷一個用戶是否允許執行某一操作。例如,Alice有獲取資源的許可,但不能創建資源。

 

身份驗證

Web API有兩種方式進行身份驗證:在宿主程序中的身份驗證和使用 HTTP Message Handlers進行身份驗證。

如果你的Web API運行在IIS中,那么身份驗證程序就是HTTP Modules,可以使用內置的asp.net身份驗證模塊進行身份驗證,也可以自己寫一個身份驗證模塊完成自定義身份驗證。

當在宿主程序中進行身份驗證時,宿主程序會創建一個principal對象,這個對象的類實現了IPrincipal接口,用來代表當前代碼運行的安全上下文。宿主通過設置Thread.CurrentPrincipal 將主體附加到當前進程。principal包含一個關聯用戶信息的Identity 對象,如果用戶驗證通過,Identity.IsAuthenticated 屬性返回true;對於匿名請求,IsAuthenticated 返回false。關於更多的principals信息,參見Role-Based Security

使用HTTP Message Handlers 進行身份驗證

你可以在 HTTP message handler中創建身份驗證邏輯來代替使用宿主身份驗證機制,在這種機制中,message handler檢驗Http請求並設置principal。

該在何時使用HTTP Message Handler進行身份驗證呢?這里給出了一個這種的參考:

  • 一個HTTP Module觀察所有通過ASP.NET管道的請求;一個Message Handler只觀察被路由處理的Web API請求。
  • 你可以對每個路由設置一個Message Handler,這個方便了針對特殊的路由設置特殊的身份驗證方案。
  • HTTP Module是IIS特有的;Message Handler則與宿主無關,因此你可以同時在web-hosting和self-hosting中使用。
  • HTTP Module參與IIS的登陸、審核等處理。
  • HTTP Module在管道中更早的執行,如果你使用Message Handler進行身份驗證,在handler執行前principal 沒有准備好。此外,在response離開Message Handler后,principal 會被恢復到之前的principal 。

綜上所述,如果你不需要支持self-hosting,HTTP Module回事更好的選擇。如果你需要支持self-hosting,那就考慮使用Message Handler吧。

 

設置Principal

如果你的程序完成了一些自定義的身份驗證邏輯,那么你必須設置愛兩個地方的principal:

  • Thread.CurrentPrincipal. 這個屬性是在.NET中設置線程 principal的標准途徑。
  • HttpContext.Current.User. 這個屬性是ASP.NET 專用的。

下面的代碼展示了如何設置principal:

private void SetPrincipal(IPrincipal principal)
{
    Thread.CurrentPrincipal = principal;
    if (HttpContext.Current != null)
    {
        HttpContext.Current.User = principal;
    }
}

對於web-hosting,你必須在這兩個地方食指principal,否則安全上下文可能會變得不一致。對於self-hosting,HttpContext.Current是null。為了確定你的代碼與宿主無關,所以在賦值之前檢查一下HttpContext.Current,就像上面的代碼那樣。

 

授權

授權發生在管道的后面一些,更接近於controller。它讓你在授權訪問資源是可以進行更細小粒度的操作。

  • Authorization filters 在controller Action之前運行。如果請求未授權,filter返回一個錯誤的response,action不會被調用。
  • 在Controller Action內部,你可以通過ApiController.User屬性訪問當前principal。例如你可能要根據用戶來過濾一個資源列表,只返回屬於該用戶的資源。

image

使用[Authorize]屬性

Web API 提供了一個內置的授權過濾器:AuthorizeAttribute。這個過濾器檢查用戶是否被授權,如果沒有,則返回 http status code 401(Unauthorized),不會調用Action。

你可以添加將過濾器添加到globally,或Controller級別,或Action級別。

globally:要為每一個Web API請求添加約束,則在全局的過濾器列表中添加AuthorizeAttribute。

public static void Register(HttpConfiguration config)
{
    config.Filters.Add(new AuthorizeAttribute());
}

 

Controller:要約束一個特殊的controller的訪問,則在controller上添加AuthorizeAttribute。

[Authorize]
public class ValuesController : ApiController
{
    public HttpResponseMessage Get(int id) { ... }
    public HttpResponseMessage Post() { ... }
}

 

Action:要約束一個特殊Action的訪問,在Action上添加AuthorizeAttribute。

public class ValuesController : ApiController
{
    public HttpResponseMessage Get() { ... }

    // Require authorization for a specific action.
    [Authorize]
    public HttpResponseMessage Post() { ... }
}

另外,你還可以約束一個controller訪問的同時允許匿名訪問特殊的Action,這需要使用[AllowAnonymous]屬性。在下面的示例中,Post方法被約束了,而Get方法允許被匿名訪問:

[Authorize]
public class ValuesController : ApiController
{
    [AllowAnonymous]
    public HttpResponseMessage Get() { ... }

    public HttpResponseMessage Post() { ... }
}

在上面的例子中,過濾器允許任何被驗證的用戶訪問受約束的方法,只有匿名用戶被拒絕。

你還可以限制一些特殊用戶或特殊角色的訪問:

// Restrict by user:
[Authorize(Users = "Alice,Bob")]
public class ValuesController : ApiController
{
}

// Restrict by role:
[Authorize(Roles = "Administrators")]
public class ValuesController : ApiController
{
}

注意:Web API中的AuthorizeAttribute過濾器是在命名空間System.Web.Http中的,在MVC Controller中有一個相似的過濾器,定義在System.Web.Mvc中,他倆不能兼容使用。

 

自定義 Authorization Filters

一個自定義authorization filter衍生自一下幾個類型:

  • AuthorizeAttribute. 擴展這個類來完成基於當前用戶和角色的授權邏輯。
  • AuthorizationFilterAttribute. 擴展這個類完成同步的授權邏輯,這種方式必須要基於當前用戶和角色。
  • IAuthorizationFilter. 實現這個接口來完成異步的授權邏輯。例如,如果你的授權邏輯使用了異步的IO或網絡調用(如果你的授權邏輯是CPU-Bound,那就和簡單的衍生自AuthorizationFilterAttribute一樣,因為你不需要寫一個異步方法)

The following diagram shows the class hierarchy for the AuthorizeAttribute class.

下面的圖片展示了AuthorizeAttribute的類層級:

image

在Controller Action中授權

有時候,你可能允許一個請求繼續下去,但根據principal改變其行為。例如,你返回的信息會依賴用戶角色發生改變。在Controller的方法中,你可以通過ApiController.user屬性得到當前的principal。

public HttpResponseMessage Get()
{
    if (User.IsInRole("Administrators"))
    {
        // ...
    }
}

ps. 勉強的翻譯了一下這篇文章的內容,就當是學習的筆記吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM