Visual

17 基于 Claim 和 Policy 的授权 上.mp4 (99.57MB)

一句话的事儿

  • User分类成Role,然后Role能够做什么事情,通过Claim
  • 若单纯的通过Claim这个大熔炉集合显然显得很冗余,那么新添的一个Policy从而对大熔炉进行整合

Claim

  • 一部分信息
  • Name-Value
  • 可以来自内部或外部
  • 基于策略的(Policy)

Docs:Claims-based authorization in ASP.NET Core

UserController 中操作 Claim

User 与 Claim 的关系类似与 User 与 Role 的关系。

  1. public async Task<IActionResult> ManageClaims(string id)
  2. {
  3. var user = await _userManager.Users.Include(x => x.Claims)
  4. .Where(x => x.Id == id).SingleOrDefaultAsync();
  5. if (user == null)
  6. {
  7. return RedirectToAction("Index");
  8. }
  9. // 筛选出该 User 没有的 Claim
  10. var leftClaims = ClaimTypes.AllClaimTypeList.Except(user.Claims.Select(x => x.ClaimType)).ToList();
  11. var vm = new ManageClaimsViewModel
  12. {
  13. UserId = id,
  14. AvailableClaims = leftClaims
  15. };
  16. return View(vm);
  17. }
  18. [HttpPost]
  19. public async Task<IActionResult> ManageClaims(ManageClaimsViewModel vm)
  20. {
  21. var user = await _userManager.FindByIdAsync(vm.UserId);
  22. if (user == null)
  23. {
  24. return RedirectToAction("Index");
  25. }
  26. var claim = new IdentityUserClaim<string>
  27. {
  28. ClaimType = vm.ClaimId,
  29. ClaimValue = vm.ClaimId
  30. };
  31. user.Claims.Add(claim);
  32. var result = await _userManager.UpdateAsync(user);
  33. if (result.Succeeded)
  34. {
  35. return RedirectToAction("EditUser", new { id = vm.UserId });
  36. }
  37. ModelState.AddModelError(string.Empty, "编辑用户Claims时发生错误");
  38. return View(vm);
  39. }
  40. [HttpPost]
  41. public async Task<IActionResult> RemoveClaim(string id, string claim)
  42. {
  43. var user = await _userManager.Users.Include(x => x.Claims)
  44. .Where(x => x.Id == id).SingleOrDefaultAsync();
  45. if (user == null)
  46. {
  47. return RedirectToAction("Index");
  48. }
  49. var claims = user.Claims.Where(x => x.ClaimType == claim).ToList();
  50. foreach (var c in claims)
  51. {
  52. user.Claims.Remove(c);
  53. }
  54. var result = await _userManager.UpdateAsync(user);
  55. if (result.Succeeded)
  56. {
  57. return RedirectToAction("EditUser", new { id });
  58. }
  59. ModelState.AddModelError(string.Empty, "编辑用户Claims时发生错误");
  60. return RedirectToAction("ManageClaims", new { id });
  61. }

Policy(策略)

  • 注册 Policy
  • 使用 Policy 进行授权

Docs:Policy-based authorization in ASP.NET Core

添加策略

通过 Role 和 Claim 添加策略:

  1. services.AddAuthorization(options =>
  2. {
  3. options.AddPolicy("仅限管理员", policy => policy.RequireRole("Administrators"));
  4. options.AddPolicy("编辑专辑", policy=> policy.RequireClaim("Edit Albums"));
  5. });

两个注意事项

  1. 如果登录账号时抛出 No IUserTokenProvider is registered 异常,可以通过 AddDefaultTokenProviders() 解决
  2. 修改用户的 Claim 后,需重新登录才能生效。如果不想重新登录,可以通过 RefreshSignInAsync 解决
    1. PS:这会带来一些别的问题 Update user claims without updating authentication time