我应该在哪里插入Asp.net WebAPI中的授权?

ash*_*ina 25 security authorization asp.net-web-api

我看到我有三个可能的地方插入我的东西在管道中

1)     AuthorizationFilters

2)     Action Filters

3)     DelegatingHandler
Run Code Online (Sandbox Code Playgroud)

最明显的一个是AuthorizationFilters,我可以使用自定义授权属性来装饰我的动作/控制器.说.. MyCustomAuthorizationAttribute.

由于HTTP消息处理程序处于处理管道的第一阶段.把它放在那里是否有意义?

我现在的授权仅仅意味着检查标头中的标记,该标记在认证后被提供给客户端.

Mar*_*nes 37

2014年7月更新

我的原始答案涵盖WebApi 1. WebApi 2有一些变化,即现在有一个IAuthenticationFilter意义,你可以将身份验证逻辑移出DelegatingHandler更优雅的一点.

有一个项目的NuGet 这里,提供IAuthenticationFilter的实现,也说明了一些背景将其引进.

OWIN中间件现在也许是实现你的验证逻辑最好的地方-有证书认证的例子在这里在这里和基本身份验证OWIN中间件这篇博客前者的例子是,因为它演示了如何使用基础的最好的一个AuthenticationHandler班.

关于AuthorizationFilters遗体的建议基本没有变化.

结束更新

通常...

使用DelegatingHandler进行身份验证...即谁有人.使用它来设置线程和用户上下文的原则,添加声明等.您也可以在此处放置授权逻辑,但是在全球范围内.我个人总是使用AuthorizationFilters进行授权.

使用AuthorizationFilters限制控制器和行动,以具体的人.当您可以使用claim,principal,url或http请求参数中的信息推断其权限时,可以使用这些权限.默认授权过滤器可用于限制对匿名用户或角色的访问(如果设置为委托处理程序) - 显然,如果需要,您也可以实现自己的AuthorizationFilters.

偶尔使用ActionFilters当你需要使用消息内容做出关于授权的决定时,例如你需要访问实体上的属性来决定他们是否有访问权限(显然要小心这个(!)).

注意:

AuthorizationFilters读取正文内容之前调用它们因此它们无权访问消息正文以进行授权决策这就是为什么ActionFilters具体OnActionExecuting用于偶尔引发身份验证错误的原因.

所以

在你的场景中,我会简单DelegatingHandler地拿你的标题并设置主体.

public class CustomAuthenticationMessageHandler : DelegatingHandler
{


    public CustomAuthenticationMessageHandler ()
    {

    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
                                                           CancellationToken cancellationToken)
    {
        Authenticate(request);

        return base.SendAsync(request, cancellationToken);
    }

    protected virtual void Authenticate(HttpRequestMessage request)
    {

        var authorisationHeader = request.Headers.Authorization;

        if (authorisationHeader == null)
        {
            return;
        }

        //Ensure you are happy with the header contents then

        {
            var principal = new GenericPrincipal(//new Identity , //Roles);
            Thread.CurrentPrincipal = principal;
            HttpContext.Current.User = principal;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

然后AuthorizationFilters用来限制访问:

    [Authorize]
    public string Get()
    {

    }

    [Authorize(Roles = "Admin")]
    public string GetAdminOnly()
    {

    }
Run Code Online (Sandbox Code Playgroud)

注册全局身份验证

config.MessageHandlers.Add(new CustomAuthenticationMessageHandler());
Run Code Online (Sandbox Code Playgroud)

这意味着在每个请求中,主体将被设置为null或有效标识.它不会处理授权,即不会拒绝访问任何控制器或操作.

开始保护资源

使用标准或自定义[授权]属性定位受保护的控制器和操作.或全球注册:

config.Filters.Add(new AuthorizeAttribute());
Run Code Online (Sandbox Code Playgroud)

并且只有白名单列出了您希望使用该[AllowAnonymous]属性取消保护的控制器和操作 .

如果您只想在某些路由上进行身份验证

然后你可以修改你DelegatingHandler的一点来设置InnerHandler路由到正确的控制器,例如

public CustomAuthenticationMessageHandler(HttpConfiguration configuration)
{
       InnerHandler = new HttpRoutingDispatcher(configuration);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的路线上指定这个处理程序,如下所示:

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "myurl",
            defaults: new {},
            constraints: new {},
            handler: new CustomAuthenticationHandler(config)
            );
Run Code Online (Sandbox Code Playgroud)