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 没有的 Claim
var 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