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

IdentityServer与JWT双重认证配置及ClaimsPrincipal问题咨询

问题描述

现有中心服务已使用IdentityServer作为认证方式,需保留该方式并新增JWT Bearer Token支持,有以下疑问:

  1. 是否可同时启用两种认证方式?
  2. 认证检查何时执行?是否都会运行?顺序是否重要?其中一种失败会怎样?

调试新Token时曾注释IdentityServer认证代码,当前中间件配置如下:

appBuilder.UseIdentityServerBearerTokenAuthentication(new 
  IdentityServerBearerTokenAuthenticationOptions
  {
    "Authority" = ...,
    "ValidationMode" = ValidationMode.Both,
    "RequireHttps" = ...,
    "RequiredScopes" = ...,
    "AutomaticRefreshInterval" = ...,
    "ValidationResultCacheDuration" = ...
  });

appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
  //"AuthenticationType" = DefaultAuthenticationTypes.ExternalBearer,  // ???
  "AuthenticationMode" = AuthenticationMode.Passive, // what is best???  
  "AllowedAudiences" = new[] { audience },
  "TokenValidationParameters" = new TokenValidationParameters
    {
      "ValidateIssuerSigningKey" = true,
      "ValidateAudience" = false,
      "ValidateIssuer" = false,
      "IssuerSigningKey" = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(secret),
      //"ValidIssuer" = issuer
      //"ValidAudience" = audience,
    }
  });

当前遇到的障碍:我们通过AuthorizationFilterAttribute实现授权检查,代码如下:

public override Task OnAuthorizationAsync(HttpActionContext ac, CancellationToken cancellationToken)
{
    if (!(ac.RequestContext.Principal is ClaimsPrincipal p) 
|| !p.Identity.IsAuthenticated)
   {
      // 此处返回未授权,因为Principal不是ClaimsPrincipal类型
   }

    return Task.FromResult(true);
}

目前请求中仅能看到包含匿名WindowsIdentities的默认WindowsPrincipal,需要指导如何创建并添加ClaimsPrincipal。


解决方案

多认证方式相关疑问解答

  1. 是否可同时启用两种认证?
    可以同时启用两种认证方式,ASP.NET支持配置多个认证中间件,只要配置逻辑正确就能共存。

  2. 认证检查的执行逻辑

  • 执行时机:认证中间件在请求管道的早期阶段执行,早于授权逻辑(UseAuthorization),确保授权前完成身份验证。
  • 是否都会运行:取决于认证模式(AuthenticationMode):
    • Active模式:中间件会主动尝试验证请求中的令牌;
    • Passive模式:仅当通过[Authorize(AuthenticationSchemes = "指定认证类型")]明确指定时,才会触发验证。
  • 顺序是否重要:非常重要。如果多个Active模式中间件共存,会按注册顺序依次尝试验证,只要其中一个验证成功,后续Active中间件就会跳过;若所有Active中间件验证失败,才会触发指定使用的Passive中间件验证。
  • 单种认证失败的影响:Active模式中间件验证失败时,默认直接返回401未授权;Passive模式仅在被指定使用时,验证失败才会返回401,否则不影响其他认证流程。

中间件配置优化

针对你的JWT Bearer配置,建议调整如下:

  • 设置AuthenticationType:给JWT认证指定唯一标识(比如"JwtBearer"),方便后续在授权特性中指定使用,也能区分不同认证来源。
  • 调整AuthenticationMode:如果希望该中间件主动验证所有请求的JWT令牌,设为AuthenticationMode.Active;如果仅在特定接口使用,保持Passive并在对应接口的[Authorize]中指定AuthenticationSchemes = "JwtBearer"。

修改后的JWT配置示例:

appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
  AuthenticationType = "JwtBearer",
  AuthenticationMode = AuthenticationMode.Active, // 根据业务需求选择模式
  AllowedAudiences = new[] { audience },
  TokenValidationParameters = new TokenValidationParameters
    {
      ValidateIssuerSigningKey = true,
      ValidateAudience = false,
      ValidateIssuer = false,
      IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(secret),
    }
});

解决ClaimsPrincipal缺失问题

当前仅能获取WindowsPrincipal,说明认证中间件未成功验证令牌并生成ClaimsPrincipal,可按以下步骤处理:

  1. 确认请求令牌格式:JWT令牌需放在Authorization请求头中,格式为Bearer <token>;IdentityServer令牌也需符合对应格式要求。
  2. 检查中间件注册顺序:确保认证中间件注册在UseWebApi/UseMvc之前,保证认证流程在API处理前完成。
  3. 调整授权过滤器:兼容多种Principal类型,或确保认证成功后生成ClaimsPrincipal,示例代码如下:
public override Task OnAuthorizationAsync(HttpActionContext ac, CancellationToken cancellationToken)
{
    ClaimsPrincipal principal = null;

    // 尝试获取已认证的ClaimsPrincipal
    if (ac.RequestContext.Principal is ClaimsPrincipal cp)
    {
        principal = cp;
    }
    // 若为WindowsPrincipal,转换为ClaimsPrincipal(仅当启用Windows认证时适用)
    else if (ac.RequestContext.Principal is WindowsPrincipal wp)
    {
        principal = new ClaimsPrincipal(wp.Identity);
    }

    if (principal == null || !principal.Identity.IsAuthenticated)
    {
        ac.Response = ac.Request.CreateResponse(HttpStatusCode.Unauthorized);
        return Task.CompletedTask;
    }

    return Task.CompletedTask;
}
  1. 开启认证日志:启用Microsoft IdentityModel的日志功能,查看认证过程中的错误信息,定位令牌验证失败的具体原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 07:12:19