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

React异步调用两次Axios Post遇401及.NET Core JWT中间件问题

问题排查:React + .NET Core 二次请求鉴权异常

场景说明

React项目通过Axios在useEffect异步函数中先后发起两个POST请求:

  • 先调用getBookId接口获取书籍ID
  • 再用该ID调用getBookDetail接口获取书籍详情
    两个请求均携带Auth0生成的Authorization Token。

现象:第一个请求成功,第二个请求返回401;后端JwtMiddleware能触发并设置HttpContext.User,但无法进入控制器逻辑,抛出500内部错误。

尝试过两种中间件顺序:

  • 将UseMiddleware<JwtMiddleware>放在UseAuthorization之后、MapControllers之前:出现上述异常
  • 将其放在UseAuthentication之前:控制器中HttpContext.User无法被正确设置

相关代码

React前端代码

const BookStore = () => {
    useEffect(() => {
        const getBook = async() => {
            const {data: bookId} = await getBookId('testName')
            const {data: bookDetails} = await getBookDetails(bookId)
        }
        getBook()
    }, [])
}

export function getBookId(name:string) {
    return axios.post<string>('/api/getBookId', {name}, {
        headers: {
            "content-type": "application/json",
            Authorization: `Bearer ${token}`
        }
    })
}

export function getBookDetail(id:string) {
    return axios.post<string>('/api/getBookDetail', {id}, {
        headers: {
            "content-type": "application/json",
            Authorization: `Bearer ${token}`
        }
    })
}

.NET Core JwtMiddleware代码

public class JwtMiddleware
{
    private readonly RequestDelegate _next;

    public JwtMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            context.Request.Headers.TryGetValue("Authorization", out var headerAuth);
            var jwtToken = headerAuth.First()?.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)[1];

            var handler = new JwtSecurityTokenHandler();
            var jwtSecurityToken = handler.ReadJwtToken(jwtToken);
            var userName = jwtSecurityToken.Claims.First(c => c.Type == "userName").Value;
            // 此处存在未定义变量sub的错误
            var userId = sub.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)[1];

            var claims = new List<Claim>
            {
                new("userName", userName),
                new("userId", userId),
            };

            var userIdentity = new ClaimsIdentity(claims, "AppUser");
            var userPrincipal = new ClaimsPrincipal(userIdentity);
            context.User = userPrincipal;

            await _next(context);
        }
        catch (Exception e)
        {
            Console.WriteLine("JwtMiddleware error: {0}", e);
            throw;
        }
    }
}

Program.cs中间件配置

app.UseAuthentication();
app.UseAuthorization();

app.UseMiddleware<JwtMiddleware>();
app.MapControllers();

app.Run();

问题分析与解决方案

1. JwtMiddleware代码致命错误

Invoke方法中var userId = sub.Split(...)的sub变量未定义,会直接抛出异常,导致第二个请求进入中间件时触发500错误,前端感知为401(可能是后端异常处理返回了错误状态码)。

修复:从JWT Claims中正确获取sub字段:

var sub = jwtSecurityToken.Claims.First(c => c.Type == "sub").Value;
var userId = sub.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)[1];

2. 中间件顺序错误

.NET Core中间件执行顺序决定了鉴权逻辑的生效时机:

  • UseAuthentication负责验证Token并初始化HttpContext.User
  • UseAuthorization基于HttpContext.User完成权限校验
  • 自定义JwtMiddleware若用于扩展/覆盖鉴权逻辑,必须放在UseAuthentication之后、UseAuthorization之前

正确配置顺序:

app.UseAuthentication();
// 自定义中间件放在鉴权初始化后、权限校验前
app.UseMiddleware<JwtMiddleware>();
app.UseAuthorization();

app.MapControllers();

app.Run();

原因:

  • 若放在UseAuthorization之后,权限校验已完成,修改HttpContext.User不会生效,且中间件异常会直接终止请求
  • 若放在UseAuthentication之前,默认鉴权逻辑会覆盖自定义设置的HttpContext.User

3. 前端潜在问题

检查两次请求中token是否一致,是否在第一个请求后过期或被意外修改,可在两个请求函数中打印token确认。


补充说明

自定义JwtMiddleware可以用来设置HttpContext.User,但必须严格遵循中间件执行顺序,同时确保代码逻辑无异常,否则会导致请求中断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:34:54