.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]
添加到控制器或特定端点函数。
我想创建这种访问继承权,随着我们的发展,权利会被继承:
已验证:只能发出 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]
添加到控制器或特定端点函数。