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

.NET Core 6中AuthorizationHandler读取请求Body时出现异常行为

问题分析与解决方案

核心原因:异步操作未等待

在MyCalendarChangeAuthorizationHandler的HandleRequirementAsync方法中,调用request.Body.CopyToAsync(memStream)时未使用await关键字,导致代码跳过异步复制操作直接执行后续读取逻辑。此时内存流还未接收到请求体内容,读取结果为空字符串,反序列化失败后触发context.Fail(),返回403。

由于异步操作的执行时机不确定,偶尔请求体较小会刚好完成复制,因此出现“相同请求有时成功有时失败”的随机现象。

次要问题:请求缓冲中间件顺序错误

你在Startup.cs中将启用请求缓冲的中间件放在了UseAuthorization之后:

app.UseAuthorization();

app.Use(next => context =>
{
    context.Request.EnableBuffering();
    return next(context);
});

授权中间件执行时,请求体尚未启用缓冲,若之前有其他组件读取过请求体,后续将无法再次读取,也会导致读取空内容的情况。

修复步骤

1. 修复异步操作等待问题

修改MyCalendarChangeAuthorizationHandler代码,给异步方法添加await:

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
    MyCalendarChangeRequirement requirement)
{
    MyDto my;

    var request = _httpContextAccessor.HttpContext.Request;
    request.EnableBuffering();

    try
    {
        request.Body.Position = 0;
        using var memStream = new MemoryStream();
        // 添加await等待复制完成
        await request.Body.CopyToAsync(memStream);
        memStream.Position = 0;
        var body = new StreamReader(memStream).ReadToEnd();
        _logger.LogInformation(body);
        var calendarChange = JsonConvert.DeserializeObject<CalendarChangesDto>(body);

        if (calendarChange == null || calendarChange.someId <= 0)
        {
            context.Fail();
            _logger.LogWarning($"Message could not be parsed to {nameof(CalendarChangesDto)}");
            request.Body.Position = 0;
            return Task.CompletedTask;
        }

        // 其余无关代码
    }
    catch(Exception ex)
    {
        _logger.LogError(ex, "Error handling calendar change authorization");
        context.Fail();
        request.Body.Position = 0;
        return Task.CompletedTask;
    }
}

2. 调整请求缓冲中间件顺序

在Startup.cs中,将启用请求缓冲的中间件移至UseAuthorization之前,确保授权处理时请求体可被多次读取:

app.UseRouting();
// 先启用请求缓冲
app.Use(next => context =>
{
    context.Request.EnableBuffering();
    return next(context);
});
app.UseAuthorization();

app.UseEndpoints(routes =>
{
    routes.MapHub<MyHub>("/myHub");
    routes.MapControllers();
});

3. 额外优化建议

  • 读取完请求体后,务必将request.Body.Position重置为0,避免后续控制器的[FromBody]参数无法读取请求体。
  • 添加异常捕获逻辑,防止反序列化过程中出现异常导致授权逻辑中断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:25:28