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

Ham*_*lar 5 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()
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在启动我有

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

控制器方法是

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

点击此端点不返回任何内容,并且控制台中有警告

warn: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[0]
      Authorization failed for the request at filter 'Microsoft.AspNet.Mvc.Filters.AuthorizeFilter'.
Run Code Online (Sandbox Code Playgroud)

我能够点击其他没有成功属性的端点.

SOS,杰克

Ben*_*ers 13

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

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

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
{

}
Run Code Online (Sandbox Code Playgroud)

在我的Startup.cs ConfigureServices()部分注册:

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

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

[HttpGet]
[Authorize(Policy = "Test")]
public IActionResult Index()
{
    Return View();
}
Run Code Online (Sandbox Code Playgroud)

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

事实证明,我没有注册TestHandlerConfigureServices()的(依赖注入)部分Startup.cs.

services.AddSingleton<IAuthorizationHandler, TestHandler>();
Run Code Online (Sandbox Code Playgroud)

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

  • 为我修好了。尽管我非常喜欢在 AspNetCore 中包含 DI,但有时会混淆您必须注册的内容以及如何注册。 (3认同)
  • 我刚在这个问题上花了两天时间,结果发现这就是我需要的答案……我感觉自己像个白痴。 (2认同)

Ham*_*lar 3

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

问题是在调用AuthorizeFilter之前拒绝请求。AuthorizationHandler这是因为对于Authorize标签的每次使用,MVC 都会在管道中添加AuthorizeFilter到前面。AuthorizationHandlerAuthorizeFilter将检查当前用户身份是否已获得授权。就我而言,没有与任何用户关联的授权身份,因此这总是会失败。

一个解决方案(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();
    });
Run Code Online (Sandbox Code Playgroud)

AuthorizeFilter此处概述了覆盖的另一种方法( Override global Authorize Filter in ASP.NET Core MVC 1.0

引用此处的响应(基于 Asp.Net Core 策略的授权以 401 Unauthorized 结尾