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

ASP.NET 5 Policy-Based Authorization Handle Not Being Called

按照此处的文档,我尝试实施基于策略的身份验证方案。 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()
        {
        }
    }
}

在启动中我有

// 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";
        }

没有命中此端点 returns 并且在

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

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

紧急求救, 杰克

看看 我认为添加 options.AutomaticChallenge = true; 可以解决您的问题。

adem caglin 的评论中提到了这个问题的答案,所以支持他。

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

一个解决方案(IMO 有点 hackish)是插入一个中间件,它将在任何 MVC 代码之前执行。该中间件将为用户添加一个通用的经过身份验证的身份(如果用户还没有)。

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

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

覆盖 AuthorizeFilter 的另一种方法在此处概述 ()

引用此处的回复 ()

我把它放在这里以供参考,因为我花了太长时间才弄明白...

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

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)!

事实证明,我没有在 Startup.csConfigureServices()(依赖注入)部分注册 TestHandler

services.AddSingleton<IAuthorizationHandler, TestHandler>();

希望这可以避免有人用头撞桌子。 :|