You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server中Claim存储异常:@context.User.Identity.Name无法取值

Blazor Server中Claim存储与授权异常问题

在Blazor Server项目中遇到以下问题:

  • 使用@context.User.Identity.Name始终无法获取对应值
  • 访问带有[Authorize(Roles = "Admin,Staff")]特性的页面时,始终处于未授权状态,@Context值为null

项目流程:

  1. 通过AuthenticationStaffOnly类的GenerateJwtToken方法生成JWT Token
  2. 在Login.razor中将Token存入LocalStorage
  3. 调用GetAuthenticationStateAsync验证Token有效性并保存Claim,但授权逻辑未生效

Index.razor(用于输出Claim信息)

<AuthorizeView>
    <Authorized>
        <h1>Hello, @context.User.Identity?.Name </h1>
    </Authorized>
    <NotAuthorized>
        @context.User.Identity.Name
        @string.Join(",", ((ClaimsIdentity)context.User.Identity).Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value))
        <p>Your email is: @context.User.FindFirstValue("email")</p>
        <h1>คุณยังไม่ได้เข้าสู่ระบบ หรือ ไม่มีสิทธิเข้าถึงหน้านี้</h1>
    </NotAuthorized>
</AuthorizeView>

AuthenticationStaffOnly.cs

using ComEsport.Models;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace ComEsport.Services
{
    public class AuthenticationStaffOnly : AuthenticationStateProvider
    {
        private readonly ILogger<StaffService> _logger;
        private readonly IConfiguration _configuration;
        private readonly ILocalStorageService _localStorage;
        private readonly HttpClient _http;
        private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
        private readonly IHttpContextAccessor _httpContextAccessor;
        public AuthenticationStaffOnly(ILogger<StaffService> logger, IConfiguration configuration, ILocalStorageService localStorage, HttpClient http, JwtSecurityTokenHandler jwtSecurityTokenHandler, IHttpContextAccessor httpContextAccessor)
        {
            _logger = logger;
            _configuration = configuration;
            _localStorage = localStorage;
            _http = http;
            _jwtSecurityTokenHandler = jwtSecurityTokenHandler;
            _httpContextAccessor = httpContextAccessor;
        }
        /// <summary>
        /// 生成JwtToken并返回
        /// </summary>
        /// <param name="staff"></param>
        /// <returns></returns>
        public async Task<string?> GenerateJwtToken(Staff staff)
        {
            if (staff.StaffEmail == null) return null;
            byte[] Key = Convert.FromBase64String(_configuration["JWTSettings:SecretKey"]);
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Key);

            SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                new Claim(ClaimTypes.Email, staff.StaffEmail),
                new Claim(ClaimTypes.Name, staff.StaffFirstName + staff.StaffLastName),
                new Claim(ClaimTypes.Role, staff.StaffPermission)
            }),
                Expires = DateTime.UtcNow.AddMinutes(25),
                SigningCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature)
            };
            JwtSecurityToken token = _jwtSecurityTokenHandler.CreateJwtSecurityToken(descriptor);
            _logger.LogInformation("Generate Jwt Token Success from AuthenticationStaffOnly Method GenerateJwtToken");
            return _jwtSecurityTokenHandler.WriteToken(token);
        }
        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            // 从localStorage读取Jwt Token
            string jsonString = await _localStorage.GetItemAsStringAsync("access_token");
            // 解析Token数据(原存储包含TokenClass结构,需提取纯Token)
            JObject json = JObject.Parse(jsonString);
            string token = json.GetValue("TokenOrMessage").Value<string>();
            var TokenData = _jwtSecurityTokenHandler.ReadJwtToken(token);

            // 从Jwt Token创建identity和claimsPrincipal
            var claims = new List<Claim>();
            claims.AddRange(TokenData.Claims.Select(claim => new Claim(claim.Type, claim.Value)));
            var identity = new ClaimsIdentity(claims, "Jwt");
            var claimsPrincipal = new ClaimsPrincipal(identity);
            var state = new AuthenticationState(claimsPrincipal);
            NotifyAuthenticationStateChanged(Task.FromResult(state));

            return state;
        }
    }
}

调试结果

  • var TokenData = _jwtSecurityTokenHandler.ReadJwtToken(token); 变量值与预期一致,包含正确的Claim信息
  • 各变量调试状态:
    • TokenData:已正确解析JWT,包含预设的Name、Email、Role等Claim
    • claims:已成功提取TokenData中的所有Claim,列表内容符合预期
    • identity:ClaimsIdentity已关联所有Claim,认证类型为"Jwt"
    • claimsPrincipal:已正确绑定上述ClaimsIdentity
    • state:AuthenticationState已包含有效的claimsPrincipal

内容的提问来源于stack exchange,提问作者Ongarj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:30:07