这是一个旧问题,但仍然相关。leastprivilege在评论中说:
声明涉及身份验证 - 而不是权限。
这是正确的,但身份还可以包括用户类型(管理员、用户、经理等),这可以用于在API中确定权限。也许设置具有特定权限的用户角色?实际上,您还可以将角色按客户端分开以获得更多控制,例如如果CLIENT1-Admin不应具有与CLIENT2-Admin相同的权限,则可以进行划分。
因此,在您的IProfileService
中传递您的角色作为声明。
public class ProfileService : IProfileService
{
private readonly Services.IUserService _userService;
public ProfileService(Services.IUserService userService)
{
_userService = userService;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
try
{
switch (context.Client.ClientId)
{
case "CLIENT1":
{
var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "sub");
if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0)
{
var user = await _userService.GetUserAsync(long.Parse(userId.Value));
if (user != null)
{
var claims = GetCLIENT1Claims(user);
context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList();
}
}
}
break;
case "CLIENT2":
{
}
}
}
catch (Exception ex)
{
}
}
private static Claim[] GetCLIENT1Claims(User user)
{
var claims = new List<Claim>
{
new Claim("user_id", user.UserId.ToString() ?? ""),
new Claim(JwtClaimTypes.Name, user.Name),
new Claim(JwtClaimTypes.Email, user.Email ?? ""),
new Claim("some_other_claim", user.Some_Other_Info ?? "")
};
foreach (string role in user.Roles)
claims.Add(new Claim(JwtClaimTypes.Role, role));
return claims.ToArray();
}
}
然后,给你的控制器添加 [Authorize]
属性以配置特定权限。这只允许特定角色访问它们,从而设置自己的权限。
[Authorize(Roles = "CLIENT1-Admin, CLIENT2-Admin, ...")]
public class ValuesController : Controller
{
//...
}
如果您正在使用自定义的ResourceOwnerPasswordValidator来设置ResourceOwner,则上述声明也可以在身份验证中传递。您可以像以下方式一样在Validation方法中传递声明。请注意保留HTML标记。
ResourceOwnerPasswordValidator
是指验证ResourceOwner密码的类。
context.Result = new GrantValidationResult(
subject: user.UserId.ToString(),
authenticationMethod: "custom",
claims: GetClaims(user));
所以像leastprivilege所说的那样,您不希望使用IdentityServer来设置权限并将其作为声明传递(例如谁可以编辑哪个记录),因为它们太具体化并且会使令牌混乱,但是设置角色以授予它们访问不同部分的API是完全可以的。这对于用户角色来说非常合适。希望能有所帮助。