Asp.Net Core 基于策略的授权以 401 Unauthorized 结尾 [英] Asp.Net Core policy based authorization ends with 401 Unauthorized

查看:20
本文介绍了Asp.Net Core 基于策略的授权以 401 Unauthorized 结尾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个基于自定义策略的授权框架,它将有一组业务规则来授权当前登录的用户.但是,目前骨架总是以 401 Unauthorized 结束.

I am working on setting up a skeleton of custom policy based authorization which will have a set of business rules to authorized the currently logged on user. But, currently the skeleton always ends up with 401 Unauthorized.

这是我的代码,

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

public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationRequirement>
{
    public MyAuthorizationHandler()
    {
    }

    protected override void Handle(AuthorizationContext context, MyAuthorizationRequirement requirement)
    {
        context.Succeed(requirement);
    }
}

然后在 Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IAuthorizationHandler, MyAuthorizationHandler>()
        .AddAuthorization(options =>
        {
            options.AddPolicy("MyAuthorization",
                                policy => policy.Requirements.Add(new MyAuthorizationRequirement()));
        });
    }

这就是我在 HomeController (MVC 6) 中使用它的方式

And this is how I use it in my HomeController (MVC 6)

[Authorize(Policy = "MyAuthorization")]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

当我不放置 Authorize 属性时,索引视图呈现良好.但是,当我包含 Authorize 属性时,我只会收到空白视图.当我检查开发人员工具(网络)时,我会得到以下幕后细节.

When I don't put the Authorize attribute, the Index view renders fine. But, when I include the Authorize attribute, I just receive the blank view. And when I check the developer tools (Network) I get the following behind the scene details.

Request URL:http://localhost:51129/
Request Method:GET
Status Code:401 Unauthorized
Remote Address:[::1]:51129

我的需求和处理程序类的构造函数的断点被调用,但是Handler类的Handle方法的断点和Index Controller 类的方法永远不会被调用.

The breakpoints to the constructors of my requirement and handler classes are invoked, but the breakpoints to the Handle method of Handler class, and Index method of Controller class never get invoked.

推荐答案

那是因为AuthorizeFilter 为每个 [Authorize] 属性添加到管道中,需要对用户进行身份验证.

That is because the AuthorizeFilter added to the pipeline for every [Authorize] attribute requires users to be authenticated.

如果您查看源代码,您会发现即使不调用任何策略,它也可以确保用户已通过身份验证:

If you look at the source code, you will see that even without calling any policy it is making sure the user is authenticated:

// Note: Default Anonymous User is new ClaimsPrincipal(new ClaimsIdentity())
if (httpContext.User == null ||
    !httpContext.User.Identities.Any(i => i.IsAuthenticated) ||
    !await authService.AuthorizeAsync(httpContext.User, context, Policy))
{
    context.Result = new ChallengeResult(Policy.AuthenticationSchemes.ToArray());
}

该条件 httpContext.User.Identities.Any(i => i.IsAuthenticated) 对于匿名用户将是 false.

That condition httpContext.User.Identities.Any(i => i.IsAuthenticated) will be false for anonymous users.

  • AuthorizationOptions 验证用户是否经过身份验证.您可以在 AddAuthorization 配置中将其设置为 null,但即使在这种情况下,上面的 AuthorizeFilter 也会确保用户已通过身份验证
  • There is also a DefaultPolicy in the AuthorizationOptions that verifies the user is authenticated. You can set that as null in the AddAuthorization configuration, but even in this case the AuthorizeFilter above will make sure the user is authenticated

您尝试代码的最简单方法是添加一个经过身份验证的匿名用户,这样任何匿名用户都会被分配一个经过身份验证的 ClaimsPrincipal(因为它已经GenericIdentity 而不是空的 ClaimsIdentity):

The easiest way just for you to try your code would be adding an authenticated anonymous user, so any anonymous user gets assigned a ClaimsPrincipal that is authenticated (as it has a GenericIdentity instead of an empty ClaimsIdentity):

//Add this before app.UseMvc
app.Use(async (context, next) =>
{
    if (!context.User.Identities.Any(i => i.IsAuthenticated))
    {
        //Assign all anonymous users the same generic identity, which is authenticated
        context.User = new ClaimsPrincipal(new GenericIdentity("anonymous"));
    }
    await next.Invoke();

});

在一个真实的应用程序中,您可能会有一些身份验证框架,用户可以在其中进行身份验证,因此您不会遇到这个问题.

In a real app you will probably have some authentication framework where users can authenticate themselves, so you wouldn't have this problem.

否则您可能需要使用应用程序约定,并将 AuthorizeFilter 替换为您自己的调整实现,不需要经过身份验证的用户,这个答案朝着那个方向发展.

Otherwise you might need to play with the application conventions, and replace the AuthorizeFilter with your own tweaked implementation that doesn't require authenticated users, this answer goes in that direction.

这篇关于Asp.Net Core 基于策略的授权以 401 Unauthorized 结尾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆