
- 一个管理员用户可以编辑或删除其他管理员用户的角色,但不能编辑或删除自己的角色
- Func 委托无法满足的情况:
- 我们无法访问 url 中的查询字符串参数
- 你可能需要通过使用依赖注入的方式来访问其他服务
CanEditOnlyOtherAdminRolesAndClaimsHandler:
public class CanEditOnlyOtherAdminRolesAndClaimsHandler : AuthorizationHandler<ManageAdminRolesAndClaimsRequirement>{private readonly IHttpContextAccessor _httpContextAccessor;public CanEditOnlyOtherAdminRolesAndClaimsHandler(IHttpContextAccessor httpContextAccessor){_httpContextAccessor = httpContextAccessor;}protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ManageAdminRolesAndClaimsRequirement requirement){// 获取 httpContext 上下文var httpContext = _httpContextAccessor.HttpContext;var loggedInAdminId = context.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;string adminIdBeingEdited = _httpContextAccessor.HttpContext.Request.Query["userId"];// 判断用户是 Admin,并且拥有 claim.Type == "Edit Role" 且值为 trueif (context.User.IsInRole("Admin") &&context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true")){// 如果当前拥有 Admin 角色的 userId 为空,说明进入的是角色列表页面。无法判断当前登录用户的 Idif (string.IsNullOrEmpty(adminIdBeingEdited)){context.Succeed(requirement);}else if (adminIdBeingEdited.ToLower() != loggedInAdminId.ToLower()){// 成功满足需求context.Succeed(requirement);}}return Task.CompletedTask;}}
Startup 中进行配置:
// 使用声明式授权services.AddAuthorization(options =>{...options.AddPolicy("EditRolePolicy", policy => policy.AddRequirements(new ManageAdminRolesAndClaimsRequirement()));options.InvokeHandlersAfterFailure = false;});services.AddSingleton<IAuthorizationHandler, CanEditOnlyOtherAdminRolesAndClaimsHandler>();
注:为了达到视频中演示的效果,还得给 AdminController 的 ManageUserRoles 也进行权限控制。
[Authorize(Policy = "EditRolePolicy")][HttpGet]public async Task<IActionResult> ManageUserRoles(string userId){...}
