基于Asp.Net核心策略的授权以401 Unauthorized结尾

时间:2016-05-17 12:19:09

标签: asp.net-core asp.net-core-mvc asp.net-authorization

我正在设置一个基于自定义策略的授权框架,该框架将具有一组业务规则来授权当前登录的用户。但是,目前骨架总是最终得到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)

中使用它的方式
[Authorize(Policy = "MyAuthorization")]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

当我没有放置Authorize属性时,索引视图呈现正常。但是,当我包含Authorize属性时,我只会收到空白视图。当我查看开发人员工具(网络)时,我会在幕后详细信息后面得到以下信息。

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

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

1 个答案:

答案 0 :(得分:2)

这是因为为每个[Authorize]属性添加到管道的AuthorizeFilter要求用户进行身份验证。

如果查看源代码,您会看到即使没有调用任何策略,也确保用户已通过身份验证:

// 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。

  • AuthorizationOptions中还有DefaultPolicy验证用户是否已通过身份验证。您可以在AddAuthorization配置中将其设置为null,但即使在这种情况下,上面的AuthorizeFilter也会确保用户已通过身份验证

仅供您尝试代码的最简单方法是添加经过身份验证的匿名用户,以便为任何匿名用户分配经过身份验证的ClaimsPrincipal(因为它具有GenericIdentity而非一个空的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();

});

在真实的应用程序中,您可能会有一些用户可以自我验证的身份验证框架,因此您不会遇到此问题。

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

相关问题