.NET Core Web API 中基于角色的 read/write 访问

Role-based read/write access in .NET Core Web API

我想创建这种访问继承权,随着我们的发展,权利会被继承:

已验证:只能发出 GET 请求。
已验证 w/role "employee":还具有对一个特定控制器的写入权限。
已验证 w/role "admin":每个控制器上都有 read/write。

到目前为止,我只遇到过自定义策略需要特定角色的解决方案。然后将此策略应用于控制器:[Authorize(Roles = "Role")]。此解决方案的问题是我必须将 "readonly" 策略添加到所有 HttpGet 操作,即使我全局需要管理员角色也是如此。

我想消除某人忘记或不小心删除控制器上的 [Authorize] 属性的可能性。

我正在寻找一种解决方案,其中的全局设置策略允许我根据角色和 http 谓词限制访问。有点像我们在设置 CORS 时所做的,伪代码如下:

var getPolicy = new RoleBasedPolicyBuilder()
    .AnyRole().AllowHttpMethod("GET");

var employeePolicy = new RoleBasedPolicyBuilder()
    .Role("employee").AllowController(EmployeeController);

var writePolicy = new RoleBasedPolicyBuilder()
    .Role("admin").AllowAnyHttpMethod();

o.Filters.Add(new AuthorizeFilter(getPolicy));
o.Filters.Add(new AuthorizeFilter(employeePolicy));
o.Filters.Add(new AuthorizeFilter(writePolicy));

编辑:

如果您有读取访问权限的角色,第一个解决方案就可以使用。 通过阅读文档我唯一能找到的其他解决方案是实现接口 IAsyncAuthorizationFilter.

public class TestAuthorizeHandler : IAsyncAuthorizationFilter
{
    private readonly string[] methodsThatDoNotRequireSpecialRoles =
    {
        "OPTIONS",
        "HEAD",
        "GET",
    };

    private const string PostMethod = "POST";

    public Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        // we don't need users to be authenticated for routes that contain this filter
        if (context.Filters.Any(filter => filter is IAllowAnonymousFilter))
        {
            return Task.CompletedTask;
        }

        var requestMethod = context.HttpContext.Request.Method;

        // we don't want to check authorization for the given methods
        if (methodsThatDoNotRequireSpecialRoles.Any(method => method == requestMethod))
        {
            return Task.CompletedTask;
        }

        if (requestMethod == TestAuthorizeHandler.PostMethod && context.HttpContext.User.IsInRole("MyWriteMethodRoles"))
        {
            return Task.CompletedTask;
        }

        context.Result = new ForbidResult();
        return Task.CompletedTask;
    }
}

现在在您的 ConfigureServices(...) 函数中添加一个 mvc 过滤器

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc(options => {
      options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build()));
      options.Filters.Add(typeof(TestAuthorizeHandler));
   }
}

另请参阅 https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies 了解更多可能有效的方案。

上一条建议:

添加全局过滤器,要求用户在您的 ConfigureService(...) 函数中获得授权

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc(options => {
      options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder()
.AddRequirements(new RolesAuthorizationRequirement(new []{ "role1", "role2"}))
                    .RequireAuthenticatedUser()
                    .Build()));
   });
}

现在每个控制器路径都需要使用您的角色之一进行授权。如果您需要某些端点具有特定角色,您仍然需要设置它。如果您不希望某些路由使用它,您只需将 [AllowAnonymous] 添加到控制器或特定端点函数。