在identityserver4中添加用户声明

在identityserver4中添加用户声明,identityserver4,Identityserver4,我已经创建了identityserver4项目,并尝试在用户登录后添加更多声明。这是我的密码 public async Task<IActionResult> Login(LoginInputModel model) { if (ModelState.IsValid) { // validate username/password against in-memory store

我已经创建了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);
          }
公共异步任务登录(LoginInputModel)
{
if(ModelState.IsValid)
{
//根据内存存储验证用户名/密码
CoreDb.Models.User=null;
if((user=wait _userService.VerifyUser(model.Username,model.Password))!=null)
{
//var user=\u users.FindByUsername(model.Username);
wait_events.RaiseAsync(新的userloginsAccessEvent(user.Name,user.Id.ToString(),user.Name));
//仅当用户选择“记住我”时才在此处设置显式过期。
//否则,我们依赖于cookie中间件中配置的过期。
var props=新的AuthenticationProperties();
if(AccountOptions.AllowRememberLogin&&model.RememberLogin)
{
props.ispersist=true;
props.ExpiresUtc=DateTimeOffset.UtcNow.Add(AccountOptions.rememberLoginDuration);
};
添加(“方案”,AccountOptions.WindowsAuthenticationSchemeName);
//发出具有主题ID和用户名的身份验证cookie
等待HttpContext.SignInAsync(user.Id.ToString(),user.Name,“idp”,props,_userService.GetUserClaims(user.ToArray());
//IEnumerable claimsIdentity=null;
//var claimsIdentity=new claimsIdentity(_userService.GetUserClaims(user),CookieAuthenticationDefaults.AuthenticationScheme);
//等待HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,新的ClaimsPrincipal(ClaimsEntity));
//确保returnUrl仍然有效,如果有效,则重定向回授权端点或本地页面
if(_interaction.IsValidReturnUrl(model.ReturnUrl)| | Url.IsLocalUrl(model.ReturnUrl))
{
返回重定向(model.ReturnUrl);
}
返回重定向(“~/”);
}
wait_events.RaiseAsync(新用户登录失败事件(model.Username,“无效凭据”);
ModelState.AddModelError(“,AccountOptions.InvalidCredentialsErrorMessage”);
}

但是,尽管我的用户id在需求处理程序中调用api,但我没有看到我对用户的声明。添加用户声明的适当方法是什么?

必须将声明添加到响应上下文中。如果您使用的是aspnetidentity,则以下方法适用于您

确保在ConfigureServices中包括ProfileService实现并连接到IdentityServer

 .AddProfileService<ProfileService>();
.AddProfileService();

私有只读IUserClaimsPrincipalFactory 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()));

    }
//
///每当请求有关用户的声明时(例如,在令牌创建期间或通过userinfo端点),都会调用此方法
/// 
///上下文。
/// 
公共重写异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
var sub=context.Subject.GetSubjectId();
var user=await userManager.FindByIdAsync(sub);
var principal=await claimsFactory.CreateAsync(用户);
//context.AddFilteredClaims(委托人索赔);
context.IssuedClaims.AddRange(委托人索赔);
添加(新声明(“IP地址”,coreOperations.GetCurrentRequestIPAddress());
}

必须将声明添加到响应上下文中。如果您使用的是AsNetIdentity,则以下方法适用于您

确保在ConfigureServices中包括ProfileService实现并连接到IdentityServer

 .AddProfileService<ProfileService>();
.AddProfileService();

私有只读IUserClaimsPrincipalFactory 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()));

    }
//
///每当请求有关用户的声明时(例如,在令牌创建期间或通过userinfo端点),都会调用此方法
/// 
///上下文。
/// 
公共重写异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
var sub=context.Subject.GetSubjectId();
var user=await userManager.FindByIdAsync(sub);
var principal=await claimsFactory.CreateAsync(用户);
//context.AddFilteredClaims(委托人索赔);
context.IssuedClaims.AddRange(委托人索赔);
添加(新声明(“IP地址”,coreOperations.GetCurrentRequestIPAddress());
}

正如Jay已经提到的,您可以编写自己的ProfileService。如果您不使用AsNetIdentity,您可以在Login方法中添加声明,并将以下行添加到ProfileService的GetProfileDataAsync方法中:

 List<Claim> claims = context.Subject.Claims.Where(x => x.Type == JwtClaimTypes.Role).ToList();

  context.IssuedClaims.AddRange(claims);
List claims=context.Subject.claims.Where(x=>x.Type==JwtClaimTypes.Role).ToList();
context.IssuedClaims.AddRange(索赔);

正如Jay已经提到的,您可以编写自己的ProfileService。如果您不使用AsNetIdentity,您可以在Login方法中添加声明,并将以下行添加到ProfileService的GetProfileDataAsync方法中:

 List<Claim> claims = context.Subject.Claims.Where(x => x.Type == JwtClaimTypes.Role).ToList();

  context.IssuedClaims.AddRange(claims);
List claims=context.Subject.claims.Where(x=>x.Type==JwtClaimTypes.Role).ToList();
context.IssuedClaims.AddRange(索赔);

我发现了问题。我需要在ApiResource定义中添加UserClaim类型。否则,IdentityServer 4将筛选我在HttpContext.SignInAsync中添加的任何声明。您建议的方法可能类似于在登录期间添加用户声明。我会在有时间时尝试此方法。我尝试了ProfileService。它似乎适用于ResourceOwnerPasswordAndClientCredentials gr