c# - 如何使用角色在 webApi 中进行过滤
问题描述
我有这个控制器
public class WorkController : ControllerBase
{
[Authorize(Roles = "admin")]
[HttpPost("something/add")]
public async Task<IActionResult> Add()
{
//add
}
[Authorize(Roles = "admin,support")]
[HttpGet("something/get")]
public async Task<IActionResult> Get()
{
//get
}
}
授权工作正常,但我认为它可以做得更好,我只是想问一下我是否可以过滤角色并根据 http 动词允许它,比如如果发件人的角色是admin,他可以访问所有方法,如果角色是support,他只能访问 Get 方法。让这个全球化会很棒,因为我有很多方法
解决方案
我只想问是否有类似我可以过滤角色并根据http动词允许它的东西,比如如果发件人的角色是管理员,他可以访问所有方法,如果角色是支持,他只能访问获取方法。
当然。首先,您需要创建规则:
public class GlobalVerbRoleRequirement: IAuthorizationRequirement
{
public bool IsAllowed(string role, string verb)
{
// allow all verbs if user is "admin"
if(string.Equals("admin", role, StringComparison.OrdinalIgnoreCase)) return true;
// allow the "GET" verb if user is "support"
if(string.Equals("support", role, StringComparison.OrdinalIgnoreCase) && string.Equals("GET",verb, StringComparison.OrdinalIgnoreCase)){
return true;
};
// ... add other rules as you like
return false;
}
}
IsAllowed(role, verb)
(如果您有更多规则,您可能希望进一步自定义)
并告诉 ASP.NET Core 如何使用 AuthorizationHandler 处理这些规则:
public class GlobalVerbRoleHandler : AuthorizationHandler<GlobalVerbRoleRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GlobalVerbRoleHandler(IHttpContextAccessor httpContextAccessor)
{
this._httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GlobalVerbRoleRequirement requirement)
{
// check whether the user has required roles for current verb
var roles = context.User.FindAll(c => string.Equals(c.Type,ClaimTypes.Role)).Select(c => c.Value);
var verb= _httpContextAccessor.HttpContext?.Request.Method;
if(string.IsNullOrEmpty(verb)){ throw new Exception($"request cann't be null!"); }
foreach(var role in roles){
if(requirement.IsAllowed(role,verb)){
context.Succeed(requirement);
return Task.CompletedTask;
}
}
context.Fail();
return Task.CompletedTask;
}
}
最后别忘了在启动时注册相关服务:
services.AddHttpContextAccessor();
services.AddScoped<IAuthorizationHandler, GlobalVerbRoleHandler>();
services.AddAuthorization(opts =>{
opts.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddRequirements(new GlobalVerbRoleRequirement())
.Build();
});
现在everyone[Authorize]
也会根据当前的HTTP动词自动检查角色。
[Authorize]
public class WorkController : ControllerBase
{
[HttpPost("something/add")]
public async Task<IActionResult> Add()
{
//add
}
[HttpGet("something/get")]
public async Task<IActionResult> Get()
{
//get
}
}
推荐阅读
- elasticsearch - org.elasticsearch 6.4.3 来自嵌套字段的查询值,无论其级别如何
- android - 为嵌套的 RecyclerViews 编写 Espresso UI 测试的正确方法是什么
- typescript - 使用 NX 将 typescript 代码编译成单个文件
- ansible - 在 Ansible 中读取 Windows 主机上的文件
- docker - luarocks install 返回一个非零代码:132(安装kong)
- javascript - 通过 JavaScript 向 Python 发送简单的 Ajax 请求
- apache - 从子网服务到互联网
- reactjs - 将单个 Switch 中的路由拆分为多个组件
- c# - EF Core 包含 Concat 字符串
- javascript - ServiceWorker 如何通过向所有订阅者推送来触发刷新/重新加载?