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

ASP.NET Core 2.0混合认证场景下,API如何从JWT令牌获取声明?

解决ASP.NET Core 2.0混合认证中API端获取JWT声明的问题

嘿,我来帮你搞定这个混合认证的问题!其实API端获取JWT声明的方式和Web端用Cookie认证的方式几乎完全一样,核心都是通过HttpContext.User来访问声明,但需要先确保API请求使用的是JWT认证方案,我来一步步给你讲清楚:

一、API端获取JWT声明的基本方式

只要API请求通过JWT认证成功,你就可以像Web控制器里那样直接用User对象(或者HttpContext.User)来获取声明,比如:

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    [HttpGet("profile")]
    public IActionResult GetUserProfile()
    {
        // 获取所有声明
        var allClaims = User.Claims.Select(c => new { c.Type, c.Value });
        
        // 获取特定声明(比如用户名、邮箱)
        var username = User.FindFirst(ClaimTypes.Name)?.Value;
        var email = User.FindFirst(ClaimTypes.Email)?.Value;
        
        return Ok(new { Username = username, Email = email, AllClaims = allClaims });
    }
}

二、关键:确保API请求使用JWT认证方案

你当前的配置里默认认证方案是myApp_cookie,所以API请求即使带了JWT令牌,也会走Cookie认证逻辑,导致拿不到JWT里的声明。有两种方式解决这个问题:

方式1:给API控制器/Action指定认证方案

直接在API控制器或者单个Action上添加[Authorize]特性,并明确指定使用JwtBearer方案:

[ApiController]
[Route("api/[controller]")]
// 给整个API控制器指定JWT认证方案
[Authorize(AuthenticationSchemes = "JwtBearer")]
public class UserController : ControllerBase
{
    // ... 你的API方法
}

这种方式简单直接,适合API和Web路由区分明确的场景。

方式2:配置动态认证方案(推荐)

通过PolicyScheme让系统自动根据请求判断使用Cookie还是JWT认证,不用手动给每个API加特性。修改你的MyAuthenticationConfig方法如下:

public static void MyAuthenticationConfig(IServiceCollection services, IConfiguration configuration) 
{ 
    services.AddAuthentication(options => 
    { 
        // 设置动态方案为默认认证/挑战方案
        options.DefaultAuthenticateScheme = "DynamicAuthScheme";
        options.DefaultChallengeScheme = "DynamicAuthScheme";
    })
    // 添加动态选择的PolicyScheme
    .AddPolicyScheme("DynamicAuthScheme", "Dynamic Authentication", options =>
    {
        options.ForwardDefaultSelector = context =>
        {
            // 判断请求头是否包含Bearer令牌,是的话用JWT认证
            var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
            if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
            {
                return "JwtBearer";
            }
            // 其他情况默认用Cookie认证
            return "myApp_cookie";
        };
    })
    // 以下是你原来的Cookie、OAuth、JWT配置,保持不变
    .AddCookie("myApp_cookie", options => 
    { 
        options.AccessDeniedPath = "/Unauthorized"; 
        options.LoginPath = "/Login"; 
    }) 
    .AddCookie("social_auth_cookie") 
    .AddOAuth("LinkedIn", options => 
    { 
        options.SignInScheme = "social_auth_cookie"; 
        options.ClientId = "my_client_id"; 
        options.ClientSecret = "my_secret"; 
        options.CallbackPath = "/linkedin-callback"; 
        options.AuthorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization"; 
        options.TokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken"; 
        options.UserInformationEndpoint = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address,picture-url,picture-urls::(original))"; 
        options.Scope.Add("r_basicprofile"); 
        options.Scope.Add("r_emailaddress"); 
        options.Events = new OAuthEvents { OnCreatingTicket = OnCreatingTicketLinkedInCallBack, OnTicketReceived = OnTicketReceivedCallback }; 
    }) 
    .AddFacebook(options => 
    { 
        options.SignInScheme = "social_auth_cookie"; 
        options.AppId = "my_app_is"; 
        options.AppSecret = "my_secret"; 
        options.Events = new OAuthEvents { OnCreatingTicket = OnCreatingTicketFacebookCallback, OnTicketReceived = OnTicketReceivedCallback }; 
    }) 
    .AddGoogle(options => 
    { 
        options.SignInScheme = "social_auth_cookie"; 
        options.ClientId = "my_id.apps.googleusercontent.com"; 
        options.ClientSecret = "my_secret"; 
        options.CallbackPath = "/google-callback"; 
        options.Events = new OAuthEvents { OnCreatingTicket = OnCreatingTicketGoogleCallback, OnTicketReceived = OnTicketReceivedCallback }; 
    }) 
    .AddJwtBearer("JwtBearer", jwtBearerOptions => 
    { 
        jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters 
        { 
            ValidateIssuerSigningKey = true, 
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_secret")), 
            ValidateIssuer = true, 
            ValidIssuer = "my-api", 
            ValidateAudience = true, 
            ValidAudience = "my-client", 
            ValidateLifetime = true, 
            ClockSkew = TimeSpan.FromMinutes(5) 
        }; 
    }); 
}

这个配置会自动检测请求:如果请求头里有Authorization: Bearer {token},就用JWT认证;否则用Cookie认证,完美适配你的混合场景。

三、验证一下

当API请求携带正确的JWT令牌时,User.Identity.IsAuthenticated会返回true,并且User.Claims会包含JWT里的所有声明,和你在Web端用Cookie获取声明的方式完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:44:57