【问题标题】:403 Error on JWT Role Based Authorization using .NET Core Web API 3.1使用 .NET Core Web API 3.1 进行基于 JWT 角色的授权时出现 403 错误
【发布时间】:2020-09-20 16:15:47
【问题描述】:

我在尝试使用 .NET Core Web API 3.1 版本实现基于角色的 JWT 授权时收到 403 Forbidden。下面是我的代码的样子:

    // API
[HttpGet, Route("GetAll")]
[Authorize(Roles = "Admin")]
public IEnumerable<Users> GetAllUsers(string environment) {}

// JWT Token Generation
public UserDetail GenerateToken(string userName, string password)
{
    string key = Configuration["Jwt:Key"];
    var issuer = Configuration["Jwt:Issuer"];
    var audience = Configuration["Jwt:Audience"];

    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    IdentityModelEventSource.ShowPII = true;

    //Create a List of Claims, Keep claims name short    
    var roleClaims = GetRoleClaimsFor(user);

    //Create Security Token object by giving required parameters    
    var token = new JwtSecurityToken(issuer,
                    audience: audience,
                    claims: roleClaims,
                    expires: DateTime.Now.AddMinutes(15),
                    signingCredentials: credentials);

    //Generate JWT Token
    var userToken = new JwtSecurityTokenHandler().WriteToken(token);
}

// StartUp.cs
public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(opt =>
        {
            opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opt.DefaultChallengeScheme = Configuration["Jwt:Policy"];
        }).AddJwtBearer(Configuration["Jwt:Policy"], options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,

                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };
        });

        // JWT Authorization configuration
        services.AddAuthorization(auth =>
        {
            auth.AddPolicy(Configuration["Jwt:Policy"], new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireClaim(ClaimTypes.Name, Configuration["Jwt:RequiredClaim"]).Build());
        });
    }
    
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {   
         app.UseAuthentication();
         app.UseAuthorization();
    }

private IList<Claim> GetRoleClaimsFor(UserPrincipal user)
    {
        var roleClaims = new List<Claim>();
        UserRoles = new List<string>();

        // Pull only groups where user belongs to
        PrincipalSearchResult<Principal> groups = user.GetGroups();

        // Filter user groups related to GBITs application alone
        var gbitsGroups = (from grp in groups
                           select grp);

        // Loop through gbitsGroups and assign the related role 
        foreach (GroupPrincipal gbitsGrp in gbitsGroups)
        {
            try
            {
                // Pull UserGroup related Permissions
                var roles = _userGroupPermissionRepository.GetUserGroupPermissionFor(gbitsGrp.Name);
                // Loop through UserGroupPermissions to create Claims
                foreach (var role in roles)
                {
                    var claim = new Claim(role.UserGroup.GroupName, role.Permission.PermissionName);
                    roleClaims.Add(claim);
                }
                // Load Roles collection
                IList<string> usrRoles = (from role in roles
                         select role.Permission.PermissionName).ToList();
                UserRoles.AddRange(usrRoles);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        return roleClaims;
    }

验证令牌后,我能够运行并查看所有角色作为 Principal.Identity 的声明。但是角色没有按预期工作。

【问题讨论】:

  • 能否请您分享一下GetRoleClaimsFor方法的详细代码,您似乎没有添加声明角色或者您错过了RequiredClaim值。
  • 谢谢白兰度。我已经用 GetRoleClaimsFor 方法修改了代码 sn-p(请参阅它的底部)。如果您需要更多详细信息,请告诉我。
  • 白兰度。现在通过将角色声明类型更改为“ClaimsType.Role”一切正常
  • 是的,我也猜你可能使用了错误的角色声明类型。我建议您可以将其回复为答案并标记它。这样其他面临相同错误的人可以更轻松地找到问题。

标签: c# asp.net-core .net-core asp.net-core-webapi


【解决方案1】:

将声明创建为 ClaimsType.Role 而不是自定义字符串解决了这个问题。下面是重构后的 GetClaimsFor 方法

private IList<Claim> GetRoleClaimsFor(UserPrincipal user)
{
    var roleClaims = new List<Claim>();
    UserRoles = new List<string>();

    // Pull only groups where user belongs to
    PrincipalSearchResult<Principal> groups = user.GetGroups();

    // Filter user groups related to GBITs application alone
    var gbitsGroups = (from grp in groups
                       select grp);

    // Loop through gbitsGroups and assign the related role 
    foreach (GroupPrincipal gbitsGrp in gbitsGroups)
    {
        try
        {
            // Pull UserGroup related Permissions
            var roles = _userGroupPermissionRepository.GetUserGroupPermissionFor(gbitsGrp.Name);
            // Loop through UserGroupPermissions to create Claims
            foreach (var role in roles)
            {
                var claim = new Claim(ClaimsType.Role, role.Permission.PermissionName);
                roleClaims.Add(claim);
            }
            // Load Roles collection
            IList<string> usrRoles = (from role in roles
                     select role.Permission.PermissionName).ToList();
            UserRoles.AddRange(usrRoles);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    return roleClaims;
}

【讨论】:

    猜你喜欢
    • 2020-12-01
    • 2020-05-21
    • 2020-05-27
    • 2021-03-12
    • 2020-05-19
    • 2018-12-05
    • 2016-07-20
    • 2019-07-07
    • 1970-01-01
    相关资源
    最近更新 更多