首页 > 解决方案 > 登录到托管的 Blazor Wasm 应用程序时如何在令牌中附加声明?

问题描述

我创建了一个带有身份的托管 Blazor Wasm。我已经创建了一个用户。我还添加了一些声明。

var adminClaims = new List<Claim>
{
   new Claim(ClaimTypes.Role, RoleEnums.Admin),
   new Claim(CustomClaimTypes.TenantUrl, viewModel.InstitutionUrl)
};
await _userManager.AddClaimsAsync(userCreateresult.User, adminClaims);

运行上述代码后,我可以验证是否已将 2 个声明添加到AspNetUserClaims表中。

但是,当我运行应用程序时,下面的代码不起作用,即 HTML 的一部分没有显示。

<AuthorizeView Roles="Admin">
   <Authorized>
      <li class="nav-item px-3">
          <NavLink class="nav-link" href="counter">
             <span class="oi oi-plus" aria-hidden="true"></span> Counter
          </NavLink>
      </li>
      <li class="nav-item px-3">
          <NavLink class="nav-link" href="fetchdata">
              <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
          </NavLink>
      </li>
   </Authorized>
</AuthorizeView>

我尝试按照文档中的建议添加,但没有奏效。

查看用户登录位置中的代码时/Server/Areas/Identity/Pages/Account/Login.cshtml.cs,我看不到创建令牌的位置。

if (ModelState.IsValid)
{
   // This doesn't count login failures towards account lockout
   // To enable password failures to trigger account lockout, set lockoutOnFailure: true
   var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
   if (result.Succeeded)
   {
       _logger.LogInformation("User logged in.");
       return LocalRedirect(returnUrl);
   }

   //more code here...
}

怎么做,当用户登录时,发送的令牌包含他/她的所有声明。

感谢您的帮助。

标签: identityserver4blazor-client-side

解决方案


我从Felipe Gavilan 的Udemy 课程中找到了解决方案。

  1. 创建实现IProfileService的此类

    public class IdentityProfileService : IProfileService
    {
        private readonly IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory;
        private readonly UserManager<ApplicationUser> userManager;
    
        public IdentityProfileService(
            IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
            UserManager<ApplicationUser> userManager)
        {
            this.claimsFactory = claimsFactory;
            this.userManager = userManager;
        }
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var userId = context.Subject.GetSubjectId();
            var user = await userManager.FindByIdAsync(userId);
            var claimsPrincipal = await claimsFactory.CreateAsync(user);
            var claims = claimsPrincipal.Claims.ToList();
    
            var claimsFromDb = await userManager.GetClaimsAsync(user);
            var mappedClaims = new List<Claim>();
            foreach (var claim in claimsFromDb)
            {
                if (claim.Type == ClaimTypes.Role)
                    mappedClaims.Add(new Claim(JwtClaimTypes.Role, claim.Value));
                else
                    mappedClaims.Add(claim);
            }
    
            claims.AddRange(mappedClaims);
            context.IssuedClaims = claims;
        }
    
        public async Task IsActiveAsync(IsActiveContext context)
        {
            var userId = context.Subject.GetSubjectId();
            var user = await userManager.FindByIdAsync(userId);
            context.IsActive = user != null;
        }
    }
    
  2. 然后注册服务

    services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
            .AddProfileService<IdentityProfileService>(); //adding this line.
    

就这样。现在我得到嵌入在 JWT 令牌中的声明。


推荐阅读