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

Keycloak与.NET Core 7 JWT权限验证失败问题求助

身份验证失败的配置遗漏点修复

以下是导致接口无法通过身份验证的关键配置问题及修复方案:

1. Issuer(签发者)不匹配

JWT Token中的iss字段为http://localhost:2011/realms/TestInventoryRealm,但appsettings里的ServerRealm配置的是http://localhost:2011/realms/TestCompanyInventoryRealm,两者不一致会直接触发Issuer验证失败。

修复:
统一Issuer配置,将appsettings中的ServerRealm修改为与Token一致的值:

"Keycloak": {
  "ServerRealm": "http://localhost:2011/realms/TestInventoryRealm",
  // 其他配置保持不变
}

2. RSA公钥加载方式错误

Keycloak采用RSA非对称加密签名JWT,但当前代码用SymmetricSecurityKey加载公钥,这会导致签名验证失败。

修复:
替换为RsaSecurityKey加载公钥,修改JWT配置中的IssuerSigningKey:

// 解析RSA公钥
var publicKey = builder.Configuration["Keycloak:PublicKey"];
var rsa = RSA.Create();
rsa.ImportFromPem(publicKey);

options.TokenValidationParameters = new()
{
    ValidateIssuer = true,
    ValidateAudience = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    ValidIssuer = builder.Configuration["Keycloak:ServerRealm"],
    IssuerSigningKey = new RsaSecurityKey(rsa), // 使用RSA密钥替代对称密钥
};

3. 授权策略名称不匹配

Program.cs中定义的授权策略名称是"create:company",但CompanyController上标注的Policy = "company"不存在,导致策略验证失败。

修复:
统一策略名称,二选一即可:

  • 方案一:修改Controller的Policy属性
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Super Admin Role", Policy = "create:company")]
public class CompanyController : CustomBaseController
{ }
  • 方案二:修改策略定义(若需保留company作为策略名)
builder.Services.AddAuthorization(opts =>{
    opts.AddPolicy("company", policy =>{
        policy.RequireClaim("scope", new[] { "create:company", "get:company", "update:company", "delete:company" });
    });
});

4. 未配置Keycloak客户端角色读取逻辑

Keycloak的客户端角色(如Super Admin Role)存储在Token的resource_access.testcompany-inventory-client.roles路径下,但默认JWT Bearer不会自动解析该路径的角色,导致Roles = "Super Admin Role"验证失败。

修复:
通过JwtBearerOptions.Events手动解析角色:

.AddJwtBearer(options =>{
    // 其他配置保持不变
    options.Events = new JwtBearerEvents
    {
        OnTokenValidated = context =>
        {
            if (context.Principal.Identity is ClaimsIdentity identity)
            {
                var resourceAccessClaim = context.Principal.Claims.FirstOrDefault(c => c.Type == "resource_access")?.Value;
                if (!string.IsNullOrEmpty(resourceAccessClaim))
                {
                    var resourceAccessObj = JsonDocument.Parse(resourceAccessClaim);
                    var clientRoles = resourceAccessObj.RootElement.GetProperty("testcompany-inventory-client").GetProperty("roles");
                    foreach (var role in clientRoles.EnumerateArray())
                    {
                        identity.AddClaim(new Claim(ClaimTypes.Role, role.GetString()));
                    }
                }
            }
            return Task.CompletedTask;
        }
    };
});

5. 认证与授权中间件顺序颠倒

当前代码中UseAuthorization()在UseAuthentication()之前,会导致授权检查先于认证完成,触发失败。

修复:
调整中间件顺序,确保认证在前:

app.UseHttpsRedirection();
app.UseAuthentication(); // 先执行认证
app.UseAuthorization(); // 再执行授权
app.MapControllers().RequireAuthorization();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:15:42