ASP.NET 5策略授权处理程序未被调用

11

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

在实现自定义授权处理程序时,我遇到了一个问题:我的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";
        }

访问此端点不会返回任何内容,并且在控制台中会出现警告信息。

warn: Microsoft.AspNet.Mvc.Controllers.ControllerActionInvoker[0]
      Authorization failed for the request at filter 'Microsoft.AspNet.Mvc.Filters.AuthorizeFilter'.

我能成功访问其他没有该属性的端点。

SOS, 杰克


同样的问题。你解决了吗? - rob
是的,我在下面回答了,与您对adem评论的评论一致。 - Hamburglar
3个回答

24

我把这个放在这里供参考,因为我花了太长时间来弄清楚这个问题...

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

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.csConfigureServices()部分进行了注册:

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>();

希望这可以帮助别人避免在桌子上撞头。 :|


4
帮我修复了。虽然我非常喜欢在AspNetCore中包含DI,但有时候很难理解需要注册什么以及如何注册。 - mode777
谢谢指出,我也犯了同样的错误。希望 .NetCore 在未来能返回一些运行时错误而不是 403。 - Prateek Kumar Dalbehera
2
我刚刚花了两天时间解决这个问题,结果发现这就是我需要的答案... 我感觉自己像个白痴。 - Lady_A
谢谢,我已经准备切换到另一个实现,但在最后一分钟发现了这篇文章。 - Andriy Kozachuk

3
这个问题的答案在对adem caglin的评论中有所提及,因此要感谢他。
问题在于AuthorizeFilter在调用AuthorizationHandler之前拒绝了请求。这是因为每次使用Authorize标签时,MVC都会在管道中将AuthorizeFilter置于AuthorizationHandler之前。这个AuthorizeFilter检查当前用户身份是否被授权。在我的情况下,没有任何用户关联的已授权身份,因此这总是失败的。
解决方案(我认为有些hackish)是插入一个中间件,在任何MVC代码之前执行。这个中间件将为用户添加一个通用的已验证身份(如果用户还没有这样的身份)。
因此,AuthorizeFilter检查将通过,并且将执行AuthenticationHandler方法上的Handle方法,从而解决我们的问题。需要添加到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,具体步骤可以参考这个链接(在ASP.NET Core MVC 1.0中覆盖全局授权过滤器)。
引用此处的回答(Asp.Net Core基于策略的授权以401未经授权结束)。

1

我认为这可能是特定于cookieAuthentication。当我调用services.AddAuthorization()时,我会得到一个AuthorizationOptions实例,它没有AutomaticChallenge字段。 - rob
你使用哪种身份验证中间件? - adem caglin
3
如果您在没有进行身份验证的情况下使用[Authorize]属性,请参考https://dev59.com/3Zffa4cB1Zd3GeqP3iIx。 - adem caglin
1
我想那可能就是了。我在大多数路由上使用JWT身份验证,但是我在一个使用自定义[Authorize]属性的路由上不需要令牌。因此,默认的AuthorizeFilter必须拒绝该请求。我明天会研究一下。 - rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接