ASP.NET 5基于策略的授权句柄未被调用

时间:2016-05-11 02:12:07

标签: c# asp.net authorization asp.net-core

按照这里的文档,我尝试实现基于策略的身份验证方案。 http://docs.asp.net/en/latest/security/authorization/policies.html#security-authorization-handler-example

我遇到的问题是我的自定义AuthorizationHandler没有调用我的Handle方法。 (它不会扔到这里)。它还会在构造函数中注入当前的依赖项。

这是AuthorizationHandler代码。

using WebAPIApplication.Services;
using Microsoft.AspNet.Authorization;

namespace WebAPIApplication.Auth
{
    public class TokenAuthHandler : AuthorizationHandler<TokenRequirement>, IAuthorizationRequirement
    {
        private IAuthService _authService;

        public TokenAuthHandler(IAuthService authService)
        {
            _authService = authService;
        }

        protected override void Handle(AuthorizationContext context, TokenRequirement requirement)
        {
            throw new Exception("Handle Reached");
        }
    } 

    public class TokenRequirement : IAuthorizationRequirement
    {
        public TokenRequirement()
        {
        }
    }
}

在Start Up中我有

// Authorization
            services.AddSingleton<IAuthorizationHandler, TokenAuthHandler>()
                .AddAuthorization(options =>
                {
                    options.AddPolicy("ValidToken",
                        policy => policy.Requirements.Add(new TokenRequirement()));
                });

控制器方法是

// GET: api/values
        [HttpGet, Authorize(Policy="ValidToken")]
        public string Get()
        {
            return "test";
        }

点击此端点不返回任何内容,并且

控制台中有警告
warn: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[0]
      Authorization failed for the request at filter 'Microsoft.AspNet.Mvc.Filters.AuthorizeFilter'.

我能够点击其他没有成功拥有该属性的端点。

SOS, 千斤顶

3 个答案:

答案 0 :(得分:10)

我把它放在这里供参考,因为我花了太长时间搞清楚这一点...

我已经实现了自定义要求和处理程序(为测试而空了):

using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;

public class TestHandler : AuthorizationHandler<TestRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TestRequirement requirement)
    {
        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

public class TestRequirement : IAuthorizationRequirement
{

}

Startup.cs ConfigureServices()部分注册:

services.AddAuthorization(options =>
{
    options.AddPolicy("Test", policy => policy.Requirements.Add(new TestRequirement()));
    // Other policies here
}

将其添加到我的控制器方法:

[HttpGet]
[Authorize(Policy = "Test")]
public IActionResult Index()
{
    Return View();
}

但是每次请求控制器方法都会收到403错误(不是401)!

事实证明,我没有在TestHandler的{​​{1}}(依赖注入)部分注册ConfigureServices()

Startup.cs

希望这可以避免某人在他们的桌子上敲头。 :|

答案 1 :(得分:3)

对阿德姆卡格林的评论中提到了这个问题的答案,这对他来说是道具。

问题是AuthorizeFilter在调用AuthorizationHandler之前拒绝了请求。这是因为对于Authorize标记的每次使用,MVC都会在管道中的AuthorizeFilter之前添加AuthorizationHandler。此AuthorizeFilter检查是否已授权任何当前用户身份。在我的情况下,没有与任何用户关联的授权身份,因此这总是会失败。

一个解决方案(IMO有点hackish)是插入一个中间件,它将在任何MVC代码之前执行。此中间件将向用户添加通用身份验证身份(如果用户尚未拥有)。

因此,AuthorizeFilter检查将通过,Handle方法上的AuthenticationHandler方法将被执行,我们的问题将得到解决。中间件代码(需要在调用Configure之前添加到app.UseMvc();)如下所示

    app.Use(async (context, next) =>
    {
        if (!context.User.Identities.Any(i => i.IsAuthenticated))
        {
            context.User = new ClaimsPrincipal(new GenericIdentity("Unknown"));
        }
        await next.Invoke();
    });

覆盖AuthorizeFilter的另一种方法是此处概述(Override global authorize filter in ASP.NET Core MVC 1.0

引用此处的回复(Asp.Net Core policy based authorization ends with 401 Unauthorized

答案 2 :(得分:1)

看看Asp.net Core Authorize Redirection Not Happening我认为添加options.AutomaticChallenge = true;可以解决您的问题。