英语原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
本文是作者所理解和翻译的内容。
这篇文章包括两部分:身份验证和授权。
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 handler中创建身份验证逻辑来代替使用宿主身份验证机制,在这种机制中,message handler检验Http请求并设置principal。
该在何时使用HTTP Message Handler进行身份验证呢?这里给出了一个这种的参考:
综上所述,如果你不需要支持self-hosting,HTTP Module回事更好的选择。如果你需要支持self-hosting,那就考虑使用Message Handler吧。
如果你的程序完成了一些自定义的身份验证逻辑,那么你必须设置爱两个地方的principal:
下面的代码展示了如何设置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。它让你在授权访问资源是可以进行更细小粒度的操作。
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 filter衍生自一下几个类型:
The following diagram shows the class hierarchy for the AuthorizeAttribute class.
下面的图片展示了AuthorizeAttribute的类层级:
有时候,你可能允许一个请求继续下去,但根据principal改变其行为。例如,你返回的信息会依赖用户角色发生改变。在Controller的方法中,你可以通过ApiController.user属性得到当前的principal。
public HttpResponseMessage Get() { if (User.IsInRole("Administrators")) { // ... } }
ps. 勉强的翻译了一下这篇文章的内容,就当是学习的笔记吧。