如何在 ASP.NET Core 2.0 中使用基于视图的授权

How to use View Based Authorization in ASP.NET Core 2.0

我的 ASP.NET Core 2.0 Web 应用程序出现奇怪的行为,授权在控制器级别通过,但在视图级别失败。

这是 ASP.NET Core 2.0 中的错误还是我的代码有问题?

//Controller中授权成功

信息:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1] 用户授权成功:(用户名)。

//进入控制器

信息:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1] 使用参数 ((null) 执行操作方法 HomeController.Index (Bams) ) - 模型状态有效

...

//视图失败

信息:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 用户授权失败:(用户名)。

在 Startup.cs 中配置服务:

services.AddAuthorization(options => {
    options.AddPolicy("HasName", policy => policy.Requirements.Add(new HasNameRequirement()));
});

HomeController.cs:

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

有名称要求:

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

HasNameHandler:

public class HasNameHandler : AuthorizationHandler<HasNameRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasNameRequirement requirement)
    {
        var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;
        if (mvcContext != null)
        {
            var name = mvcContext.HttpContext.User.Identity.Name;
            if(name != null && name != "")
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }           

        return Task.CompletedTask;
    }
}

_Layout.cshtml:

@if (await AuthorizationService.AuthorizeAsync(User, "HasName"))
{
    ...
}

_ViewImports.cshtml:

@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

问题出在 HasNameHandler 中。

var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;

这一行是为了让我的授权块只在有 MVC 上下文时才起作用。因为视图没有访问 MVC 上下文的权限,所以基于视图的授权在没有点击 context.Succeed() 的情况下完成了授权。

我删除了它,而是使用传递到方法中的 AuthorizationContext。

var name = context.User.Identity.Name;
if(name != null && name != ""){
    context.Succeed(requirement);
}
else {
    context.Fail();
}