中英文术语对照
- Authentication - 认证,就是确定登录用户的身份。
- Authorization - 授权,就是决定一个认证过的用户能执行什么操作。
- Principal - 主体,表示一个代码运行在其上的安全上下文。
- HTTP Module - HTTP模块,IIS中的模块
- HTTP Message Handler - HTTP消息处理器
- Identity - 身份,代表一个用户,类似身份证,主体中包含一个当前用户的身份
- Host - WEB服务宿主,可以是IIS服务器,可以使自托管的服务进程
Authentication(用户认证)
ASP.NET WEB API中的用户认证可以通过HTTP模块和HTTP消息处理器两种方法实现。
1. 通过HTTP模块认证
你可以在项目中配置使用任意IIS内建的认证模块(匿名身份认证、Basic基本身份认证、Windows集成身份认证、Digest摘要式身份认证、Microsoft.NET Passport身份认证)。
认证用户时,会创建一个Principal(主体),该主体是一个IPrincipal对象,代表一个代码执行的安全上下文,通过调用属性Thread.CurrentPrincipal的设置方法将该主体设置到当前线程,主体包含一个关联的Identity(用户身份)对象,该对象包含用户信息,如果用户已经是认证通过的,则Identity.IsAuthenticated属性为true,对于匿名请求来说,该属性为false。
2. 通过HTTP消息处理器认证
如果不使用宿主提供的HTTP模块认证方法,我们也可以HTTP Message Handler来实现,这种情况下,HTTP消息处理器负责检查HTTP请求并设置Principal。我们应该什么时候使用消息处理器来处理身份验证呢?以下是我们应该权衡的要素:
- HTTP模块能监视到所有通过ASP.NET管道的请求,而HTTP消息处理器只能监视路由到WEB API的请求。
- 你可以在每个路由上设置一个消息处理器,针对不同的路由应用不同的认证策略。
- HTTP模块特定于IIS服务器,而HTTP消息处理器对宿主是透明的,所以既可以用于IIS服务器托管环境也可以用于自托管环境。
- HTTP模块能使用到IIS的日志、审计等等功能,而消息处理器不能。
- HTTP模块在ASP.NET管道前期运行,而HTTP消息处理器认证时,只有执行到HTTP消息处理器是才会设置Principal,且当响应消息离开HTTP消息处理器后,Principal会被设置回默认值。
基本上来讲,如果你不需要支持服务自托管,HTTP模块是一个更好的选择,如果你需要支持自托管,那么应该考虑使用HTTP消息处理器。
Authorization(用户授权)
授权发生在ASP.NET处理管道的末端,靠近控制器的部分,这样能让你在获取资源存取权限时有更细粒度的选择。
授权过滤器(Authorization filters)运行在控制器动作之前,如果请求是未授权的,则过滤器返回错误响应,控制器动作不会被调用。在控制器动作内部,可以通过属性Api.Controller.User获取当前主体。以下代码演示了如何使用System.Web.Http.AuthorizeAttribute属性来指定授权。
// 所有的动作都需要授权
[Authorize]
public class ValuesController : ApiController
{
public HttpResponseMessage Get(int id) { ... }
public HttpResponseMessage Post() { ... }
}
// 指定的动作需要授权
public class ValuesController : ApiController
{
public HttpResponseMessage Get() { ... }
[Authorize]
public HttpResponseMessage Post() { ... }
}
// 除了指定的动作不需要,剩下的所有动作都需要授权
[Authorize]
public class ValuesController : ApiController
{
[AllowAnonymous]
public HttpResponseMessage Get() { ... }
public HttpResponseMessage Post() { ... }
}
// 特定用户才能访问
[Authorize(Users="Alice,Bob")]
public class ValuesController : ApiController
{
}
// 具有特定角色的用户才能访问
[Authorize(Roles="Administrators")]
public class ValuesController : ApiController
{
}
// 动作内部使用授权
public HttpResponseMessage Get()
{
if (User.IsInRole("Administrators"))
{
// ...
}
}
网友评论