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

如何在ASP.NET Core Web API中仅读取JWT Token用户信息而不验证

Got it, let's break this down for you! Since you don't want to handle JWT validation locally and just need to pull the sub claim while offloading validation to a third-party API, here's a clean approach tailored to ASP.NET Core Web API:

Step 1: Use a Custom Action Filter (or Middleware)

We'll create a reusable action filter to handle three key tasks: extracting the JWT from the request, parsing the sub claim without local validation, and validating the token via your third-party API. This keeps your controller code clean and centralized.

Step 2: Implement the Custom Filter

Here's the full code for the filter, which uses IHttpClientFactory to call the third-party validation API and JwtSecurityTokenHandler to parse the token without verifying its signature:

using Microsoft.AspNetCore.Mvc.Filters;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Json;

public class JwtSubExtractorFilter : IAsyncActionFilter
{
    private readonly IHttpClientFactory _httpClientFactory;
    // Replace with your actual third-party validation API endpoint
    private const string ThirdPartyValidationEndpoint = "https://your-third-party-api.com/api/validate-token";

    public JwtSubExtractorFilter(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // 1. Extract Bearer Token from Authorization header
        if (!context.HttpContext.Request.Headers.TryGetValue("Authorization", out var authHeader) ||
            !authHeader.ToString().StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
        {
            context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedResult();
            return;
        }

        var jwtToken = authHeader.ToString().Substring("Bearer ".Length).Trim();

        try
        {
            // 2. Parse the token to get the 'sub' claim (NO local validation)
            var tokenHandler = new JwtSecurityTokenHandler();
            var parsedToken = tokenHandler.ReadJwtToken(jwtToken);
            var userId = parsedToken.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Sub)?.Value;

            if (string.IsNullOrEmpty(userId))
            {
                context.Result = new Microsoft.AspNetCore.Mvc.BadRequestObjectResult("JWT token missing required 'sub' claim");
                return;
            }

            // 3. Validate token via third-party API
            var httpClient = _httpClientFactory.CreateClient();
            var validationResponse = await httpClient.PostAsJsonAsync(ThirdPartyValidationEndpoint, new { Token = jwtToken });

            if (!validationResponse.IsSuccessStatusCode)
            {
                context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedResult();
                return;
            }

            // 4. Attach the user ID to the request context for later use
            context.HttpContext.Items["UserId"] = userId;

            // Proceed to the target action
            await next();
        }
        catch (ArgumentException)
        {
            // Catch invalid JWT format errors
            context.Result = new Microsoft.AspNetCore.Mvc.BadRequestObjectResult("Invalid JWT token format");
            return;
        }
        catch (HttpRequestException)
        {
            // Handle third-party API connectivity issues
            context.Result = new Microsoft.AspNetCore.Mvc.StatusCodeResult(StatusCodes.Status503ServiceUnavailable);
            return;
        }
    }
}

Step 3: Register Dependencies in Program.cs

You need to register the filter and IHttpClientFactory (for calling the third-party API) in your startup code:

var builder = WebApplication.CreateBuilder(args);

// Add controllers
builder.Services.AddControllers();

// Register HttpClientFactory for API calls
builder.Services.AddHttpClient();

// Register the custom filter as a scoped service
builder.Services.AddScoped<JwtSubExtractorFilter>();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthorization();

// Apply the filter globally to all endpoints (or use per-controller/action attributes)
app.MapControllers().AddEndpointFilter<JwtSubExtractorFilter>();

app.Run();

Step 4: Access the sub Claim in Your Controllers

Once the filter runs successfully, you can pull the user ID from HttpContext.Items in any controller action:

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    [HttpGet("profile")]
    public IActionResult GetUserProfile()
    {
        if (HttpContext.Items.TryGetValue("UserId", out var userId))
        {
            // Use the userId in your business logic
            return Ok(new { UserId = userId.ToString(), Message = "Profile data here" });
        }

        return Unauthorized();
    }
}
Key Notes
  • Per-Action/Controller Application: If you don't want the filter to apply globally, replace the global registration with the [ServiceFilter(typeof(JwtSubExtractorFilter))] attribute on specific controllers or actions.
  • Error Handling: The example includes basic error handling for missing tokens, invalid formats, and third-party API failures—adjust this to match your application's error response requirements.
  • No Local Validation: The ReadJwtToken method only parses the token's content; it does NOT verify the signature, expiration, or issuer. Never skip the third-party validation step—this is critical for security.
  • Token Sources: If your JWTs come from somewhere other than the Authorization header (e.g., query params, cookies), modify the token extraction logic in the filter.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:02:43