在 identityserver4 中添加用户声明
Add user claims in identityserver4
我创建了 identityserver4 项目并尝试在用户登录后添加更多声明。这是我的代码
public async Task<IActionResult> Login(LoginInputModel model)
{
if (ModelState.IsValid)
{
// validate username/password against in-memory store
CoreDb.Models.User user = null;
if (( user = await _userService.VerifyUser(model.Username, model.Password)) != null)
{
// var user = _users.FindByUsername(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Name, user.Id.ToString(), user.Name));
// only set explicit expiration here if user chooses "remember me".
// otherwise we rely upon expiration configured in cookie middleware.
var props = new AuthenticationProperties();
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
{
props.IsPersistent = true;
props.ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration);
};
props.Items.Add("scheme", AccountOptions.WindowsAuthenticationSchemeName);
// issue authentication cookie with subject ID and username
await HttpContext.SignInAsync(user.Id.ToString(), user.Name, "idp", props, _userService.GetUserClaims(user).ToArray());
//IEnumerable<ClaimsIdentity> claimsIdentity = null;
//var claimsIdentity = new ClaimsIdentity(_userService.GetUserClaims(user), CookieAuthenticationDefaults.AuthenticationScheme);
//await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
// make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
return Redirect("~/");
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
}
然而,当我在需求处理程序中调用我的 api 时,我没有看到我对用户的声明,尽管我的用户 ID 在那里。添加用户声明的合适方法是什么?
必须将声明添加到响应上下文中。如果您使用的是 aspnetidentity,那么以下方法将适用于您
确保包含 ProfileService 实现并在 ConfigureServices 连接到 IdentityServer
.AddProfileService<ProfileService>();
private readonly IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory;
在 GetProfileDataAsync 中,您可以包含新声明
/// <summary>
/// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint)
/// </summary>
/// <param name="context">The context.</param>
/// <returns></returns>
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await userManager.FindByIdAsync(sub);
var principal = await claimsFactory.CreateAsync(user);
//context.AddFilteredClaims(principal.Claims);
context.IssuedClaims.AddRange(principal.Claims);
context.IssuedClaims.Add(new Claim("IP Address", coreOperations.GetCurrentRequestIPAddress()));
}
正如 Jay 已经提到的,您可以编写自己的 ProfileService。如果您不使用 aspnetidentity,您只需在登录方法中添加声明并将这些行添加到您的 ProfileService 的 GetProfileDataAsync 方法中:
List<Claim> claims = context.Subject.Claims.Where(x => x.Type == JwtClaimTypes.Role).ToList();
context.IssuedClaims.AddRange(claims);
我创建了 identityserver4 项目并尝试在用户登录后添加更多声明。这是我的代码
public async Task<IActionResult> Login(LoginInputModel model)
{
if (ModelState.IsValid)
{
// validate username/password against in-memory store
CoreDb.Models.User user = null;
if (( user = await _userService.VerifyUser(model.Username, model.Password)) != null)
{
// var user = _users.FindByUsername(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Name, user.Id.ToString(), user.Name));
// only set explicit expiration here if user chooses "remember me".
// otherwise we rely upon expiration configured in cookie middleware.
var props = new AuthenticationProperties();
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
{
props.IsPersistent = true;
props.ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration);
};
props.Items.Add("scheme", AccountOptions.WindowsAuthenticationSchemeName);
// issue authentication cookie with subject ID and username
await HttpContext.SignInAsync(user.Id.ToString(), user.Name, "idp", props, _userService.GetUserClaims(user).ToArray());
//IEnumerable<ClaimsIdentity> claimsIdentity = null;
//var claimsIdentity = new ClaimsIdentity(_userService.GetUserClaims(user), CookieAuthenticationDefaults.AuthenticationScheme);
//await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
// make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
return Redirect("~/");
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
}
然而,当我在需求处理程序中调用我的 api 时,我没有看到我对用户的声明,尽管我的用户 ID 在那里。添加用户声明的合适方法是什么?
必须将声明添加到响应上下文中。如果您使用的是 aspnetidentity,那么以下方法将适用于您
确保包含 ProfileService 实现并在 ConfigureServices 连接到 IdentityServer
.AddProfileService<ProfileService>();
private readonly IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory;
在 GetProfileDataAsync 中,您可以包含新声明
/// <summary>
/// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint)
/// </summary>
/// <param name="context">The context.</param>
/// <returns></returns>
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await userManager.FindByIdAsync(sub);
var principal = await claimsFactory.CreateAsync(user);
//context.AddFilteredClaims(principal.Claims);
context.IssuedClaims.AddRange(principal.Claims);
context.IssuedClaims.Add(new Claim("IP Address", coreOperations.GetCurrentRequestIPAddress()));
}
正如 Jay 已经提到的,您可以编写自己的 ProfileService。如果您不使用 aspnetidentity,您只需在登录方法中添加声明并将这些行添加到您的 ProfileService 的 GetProfileDataAsync 方法中:
List<Claim> claims = context.Subject.Claims.Where(x => x.Type == JwtClaimTypes.Role).ToList();
context.IssuedClaims.AddRange(claims);