- 一个管理员用户可以编辑或删除其他管理员用户的角色,但不能编辑或删除自己的角色
- 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" 且值为 true
if (context.User.IsInRole("Admin") &&
context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true"))
{
// 如果当前拥有 Admin 角色的 userId 为空,说明进入的是角色列表页面。无法判断当前登录用户的 Id
if (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)
{
...
}