我已经能够在.net core 3.1上成功实现自己的IdentityServer4身份验证服务器,并且有一个客户端Web应用程序与其连接。客户端已成功接收访问令牌和ID。令牌包含所有用户标识信息。
我的下一个目标是将用户在客户端中具有的特权添加到HttpContext.User中,作为权利要求,在我获得令牌之后立即呈现任何其他页面。特权通过subjectId存储在与用户关联的数据库中。
我需要在哪里可以添加这些声明的帮助,以便我的授权策略可以与主体中的声明配合使用。我希望每次发行令牌时都执行该过程。
P.S。我正在使用GetClaimsFromUserInfoEndpoint = true和SaveTokens = true的身份服务器代码流。
谢谢!
答案 0 :(得分:1)
您可以在identityServer4中使用Profile sevise:
services .AddIdentityServer(x =>
{
x.IssuerUri = "null";
x.Authentication.CookieLifetime = TimeSpan.FromDays(10);
})
.
.
.
.AddProfileService<ProfileService>();
这是一个很好的参考:http://docs.identityserver.io/en/latest/reference/profileservice.html 而且ProfileService可以像这样的代码模板:
public class ProfileService : IProfileService
{
private readonly UserManager<ApplicationUser> _userManager;
public ProfileService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));
var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
var user = await _userManager.FindByIdAsync(subjectId);
if (user == null)
throw new ArgumentException("Invalid subject identifier");
var claims = GetClaimsFromUser(user,subject);
context.IssuedClaims = claims.Result.ToList();
}
public async Task IsActiveAsync(IsActiveContext context)
{
var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));
var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
var user = await _userManager.FindByIdAsync(subjectId);
context.IsActive = false;
if (user != null)
{
if (_userManager.SupportsUserSecurityStamp)
{
var security_stamp = subject.Claims.Where(c => c.Type == "security_stamp").Select(c => c.Value).SingleOrDefault();
if (security_stamp != null)
{
var db_security_stamp = await _userManager.GetSecurityStampAsync(user);
if (db_security_stamp != security_stamp)
return;
}
}
context.IsActive =
!user.LockoutEnabled ||
!user.LockoutEnd.HasValue ||
user.LockoutEnd <= DateTime.Now;
}
}
private async Task<IEnumerable<Claim>> GetClaimsFromUser(ApplicationUser user,ClaimsPrincipal subject)
{
var claims = new List<Claim>
{
new Claim(JwtClaimTypes.Subject, user.Id),
new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
};
if (!string.IsNullOrWhiteSpace(user.Name))
claims.Add(new Claim("name", user.Name));
if (!string.IsNullOrWhiteSpace(user.LastName))
claims.Add(new Claim("last_name", user.LastName));
return claims;
}
}
答案 1 :(得分:0)
您可以通过使用TokenValidated事件来实现
public class CustomJwtBearerEvents : JwtBearerEvents
{
public override async Task TokenValidated(TokenValidatedContext context)
{
var claims = context.Principal.Claims.ToList();
claims.Add(new Claim("key", "value"));
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Bearer")); }
}
然后在启动时注册
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
...
options.Events = new JwtBearerEvents();
options.EventsType = typeof(CustomJwtBearerEvents);
});