Visual
一句话的事儿
- User分类成Role,然后Role能够做什么事情,通过Claim
 - 若单纯的通过Claim这个大熔炉集合显然显得很冗余,那么新添的一个Policy从而对大熔炉进行整合
 
Claim
- 一部分信息
 - Name-Value
 - 可以来自内部或外部
 - 基于策略的(Policy)
 
Docs:Claims-based authorization in ASP.NET Core
UserController 中操作 Claim
User 与 Claim 的关系类似与 User 与 Role 的关系。
public async Task<IActionResult> ManageClaims(string id){var user = await _userManager.Users.Include(x => x.Claims).Where(x => x.Id == id).SingleOrDefaultAsync();if (user == null){return RedirectToAction("Index");}// 筛选出该 User 没有的 Claimvar leftClaims = ClaimTypes.AllClaimTypeList.Except(user.Claims.Select(x => x.ClaimType)).ToList();var vm = new ManageClaimsViewModel{UserId = id,AvailableClaims = leftClaims};return View(vm);}[HttpPost]public async Task<IActionResult> ManageClaims(ManageClaimsViewModel vm){var user = await _userManager.FindByIdAsync(vm.UserId);if (user == null){return RedirectToAction("Index");}var claim = new IdentityUserClaim<string>{ClaimType = vm.ClaimId,ClaimValue = vm.ClaimId};user.Claims.Add(claim);var result = await _userManager.UpdateAsync(user);if (result.Succeeded){return RedirectToAction("EditUser", new { id = vm.UserId });}ModelState.AddModelError(string.Empty, "编辑用户Claims时发生错误");return View(vm);}[HttpPost]public async Task<IActionResult> RemoveClaim(string id, string claim){var user = await _userManager.Users.Include(x => x.Claims).Where(x => x.Id == id).SingleOrDefaultAsync();if (user == null){return RedirectToAction("Index");}var claims = user.Claims.Where(x => x.ClaimType == claim).ToList();foreach (var c in claims){user.Claims.Remove(c);}var result = await _userManager.UpdateAsync(user);if (result.Succeeded){return RedirectToAction("EditUser", new { id });}ModelState.AddModelError(string.Empty, "编辑用户Claims时发生错误");return RedirectToAction("ManageClaims", new { id });}
Policy(策略)
- 注册 Policy
 - 使用 Policy 进行授权
 
Docs:Policy-based authorization in ASP.NET Core
添加策略
通过 Role 和 Claim 添加策略:
services.AddAuthorization(options =>{options.AddPolicy("仅限管理员", policy => policy.RequireRole("Administrators"));options.AddPolicy("编辑专辑", policy=> policy.RequireClaim("Edit Albums"));});
两个注意事项
- 如果登录账号时抛出 No IUserTokenProvider is registered 异常,可以通过 AddDefaultTokenProviders() 解决
 - 修改用户的 Claim 后,需重新登录才能生效。如果不想重新登录,可以通过 RefreshSignInAsync 解决
- PS:这会带来一些别的问题 Update user claims without updating authentication time
 
 

