美文网首页
AuthenticationScheme: Bearer was

AuthenticationScheme: Bearer was

作者: gruan | 来源:发表于2021-01-29 17:42 被阅读0次

    错误详情:

    Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler - Successfully validated the token.
    Microsoft.AspNetCore.Authorization.DefaultAuthorizationService - Authorization failed. These requirements were not met:
    RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Admin)
    Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler - AuthenticationScheme: Bearer was forbidden.
    Microsoft.AspNetCore.Hosting.Diagnostics - Request finished HTTP/2 POST https://localhost:8003/cfg.Cfg/RemoveCatgegory application/grpc - - 403 0 - 403.5567ms

    JWT 配置:

    services.AddAuthorization();
    services.AddAuthentication();
    
    #region JWT
    services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(o =>
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWTSetting.SecurityKey));
    
        o.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = JwtClaimTypes.Name,
            RoleClaimType = JwtClaimTypes.Role,
    
            ValidIssuer = JWTSetting.Issuer,
            ValidAudience = JWTSetting.Audience,
            IssuerSigningKey = key,
            //生成Token 的时候,加密了, 这里需要解密
            TokenDecryptionKey = key,
        };
    });
    

    其中 RoleClaimType 用的是 JwtClaimTypes.Role

    生成Token 配置:

    if (user != null)
    {
        var expireAt = DateTime.Now.AddDays(30);
    
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWTSetting.SecurityKey));
    
        var encryptingCredentials = new EncryptingCredentials(key, JwtConstants.DirectKeyUseAlg, SecurityAlgorithms.Aes256CbcHmacSha512);
    
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(JwtClaimTypes.Audience, JWTSetting.Audience),
                new Claim(JwtClaimTypes.Issuer, JWTSetting.Issuer),
                new Claim(JwtClaimTypes.Id, user.Account),
                new Claim(JwtClaimTypes.Role, user.Role.ToString()),
                new Claim("User", JsonSerializer.Serialize(user))
            }),
            Expires = expireAt,
            SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature),
            //加密
            EncryptingCredentials = encryptingCredentials
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var tokenString = tokenHandler.WriteToken(token);
        var tokenInfo = new TokenInfo
        {
            Token = tokenString,
            LoginOn = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.Now.ToUniversalTime()),
            ExpiressAt = new DateTimeOffset(expireAt).ToUnixTimeSeconds(),
            Name = user.Name,
            OpenID = user.OpenID,
            Succ = true,
        };
    
        return tokenInfo;
    }
    

    其中:Role 使用的是 JwtClaimTypes.Role,和 JWT 配置中的 RoleClaimType 保持一致。

    上面代码, 生成的 role, 在写到 AccessToken 之前, 还是 JwtClaimTypes.Role:

    生成Token 之前,是 role:Admin
    生成Token 之前,是 role:Admin

    上面两张图显示, 生成 AccessToken 的时候, 就是 JwtClaimTypes.Role

    但是, 用它生成的 AccessToken ,发送到服务器,却变成了:ClaimTypes.Role

    QQ图片20210129163510.png

    搞不懂是哪里把 JwtClaimTypes.Role 给换成了 ClaimTypes.Role 的。

    找了两天答案, 找到下面这段:
    oauth 2.0 - Asp.net core token based claims authentication with OpenIdConnect and angularjs: Bearer was forbidden - Stack Overflow

    policy.RequireClaim("role"); might not work OTB, as IdentityModel uses an internal mapping that converts well-known JWT claims to their ClaimTypes equivalent: here, role will be likely replaced by http://schemas.microsoft.com/ws/2008/06/identity/claims/role (ClaimTypes.Role). I'd recommend using policy.RequireRole("user") instead.

    会将 JwtClaimTypes.Role替换为等效的 ClaimTypes.Role ? 不懂是什么神仙操作。
    即然是这样,那就把 JWT 配置中的 RoleClaimType 从 JwtClaimTypes.Role 改为 ClaimTypes.Role

    o.TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = JwtClaimTypes.Name,
        RoleClaimType = ClaimTypes.Role,
    ...
    

    把生成Token 配置中的:

    new Claim(JwtClaimTypes.Role, user.Role.ToString()),
    

    改为:

    new Claim(ClaimTypes.Role, user.Role.ToString()),
    

    在运行,通过。

    相关文章

      网友评论

          本文标题:AuthenticationScheme: Bearer was

          本文链接:https://www.haomeiwen.com/subject/sgoqtltx.html