【问题标题】:Where should I plugin the Authorization in Asp.net WebAPI?我应该在哪里插入 Asp.net WebAPI 中的授权?
【发布时间】:2013-02-14 09:48:02
【问题描述】:

正如我所见,我有 3 个可能的地方可以将我的东西插入管道

1)     AuthorizationFilters

2)     Action Filters

3)     DelegatingHandler

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

因为 HTTP 消息处理程序处于处理管道的第一阶段。把它放在那里有意义吗?

现在对我而言,授权只是意味着检查标头中的令牌,该令牌在身份验证后提供给客户端。

【问题讨论】:

    标签: security asp.net-web-api authorization


    【解决方案1】:

    2014 年 7 月更新

    我最初的回答涵盖了 WebApi 1。WebApi 2 发生了一些变化,即现在有一个 IAuthenticationFilter,这意味着您可以将身份验证逻辑从 DelegatingHandler 中移出,这会更优雅一些。

    有一个 Nuget 项目 here 提供了 IAuthenticationFilter 的实现,并解释了它的介绍背景。

    OWIN 中间件现在可能是实现您的身份验证逻辑的最佳位置 - 在this blog post 中有一个证书身份验证 here 和基本身份验证 OWIN 中间件的示例,前一个示例是首选示例,因为它演示了基础AuthenticationHandler 类。

    AuthorizationFilters 上的建议基本保持不变。

    结束更新

    通常...

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

    使用AuthorizationFilters 将控制器和操作限制为特定人员。当您可以使用声明、主体、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;
            }
    
        }
    }
    

    然后使用AuthorizationFilters限制访问:

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

    注册全局认证

    config.MessageHandlers.Add(new CustomAuthenticationMessageHandler());
    

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

    开始保护资源

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

    config.Filters.Add(new AuthorizeAttribute());
    

    并且仅使用[AllowAnonymous] 属性将您希望不安全的控制器和操作列入白名单。

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

    然后您可以稍微修改您的DelegatingHandler 以将InnerHandler 设置为路由到正确的控制器,例如

    public CustomAuthenticationMessageHandler(HttpConfiguration configuration)
    {
           InnerHandler = new HttpRoutingDispatcher(configuration);
    }
    

    然后你可以像这样在你的路由上指定这个处理程序:

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

    【讨论】:

    • 这是否意味着我将在请求管道中检查每个请求的授权..如果没有授权,我可以更快地从管道中弹出..如果我假设我应该根据路由进行配置可能有一些不需要任何授权/身份验证的路由..
    • 我会通过注册消息处理程序 config.MessageHandlers.Add(new CustomAuthenticationMessageHandler()) 来为每个路由添加身份验证;授权很容易以多种方式实现。如果您的大部分站点都是安全的,一种方法是全局注册授权过滤器 config.Filters.Add(new AuthorizeAttribute());然后只需将 [AllowAnonymous] 属性添加到您希望不安全的控制器或操作上。
    • 你如何让它与自托管 WebApi 一起工作?
    • 新的IAuthenticationFilter 为您提供了另一种选择;-)
    • @Kugel 感谢您的评论 - 我已尝试为 WebApi 2 用户添加一些建议。
    猜你喜欢
    • 1970-01-01
    • 2013-09-23
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多