25

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

1)     AuthorizationFilters

2)     Action Filters

3)     DelegatingHandler

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

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

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

4

1 回答 1

37

2014 年 7 月更新

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

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

OWIN 中间件现在可能是实现您的身份验证逻辑的最佳位置 - 这里有一个证书身份验证示例,并且在这篇博文中提供了基本身份验证 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)
            );
于 2013-02-14T10:42:55.350 回答