C#开启HMACAuthentication的PUT接口接收到null参数问题
问题根因及修复方案
这个问题是ASP.NET Web API 2(从你用的IHttpActionResult可判断框架版本)的请求体流特性和HMAC校验逻辑的常见冲突,核心原因如下:
- 最常见的原因是
HMACAuthenticationAttribute在校验签名时提前读取了请求体,且未处理流的复用逻辑。ASP.NET Web API 默认的请求体是仅向前的只读流,只能读取一次:如果你的HMAC校验逻辑为了计算请求内容的哈希值,提前把请求体流读完了,后续模型绑定阶段没有内容可以读取,自然就会把MyDTO obj绑定为null,加[FromBody]也不会生效,因为根本读不到请求内容。 - 第二种可能是你读取请求体时没有启用内容缓冲,就算尝试重置流位置也会因为流不支持Seek操作失败。
修复方法
修改你的HMACAuthenticationAttribute的校验逻辑,读取请求体前先开启内容缓冲,示例代码如下:
public class HMACAuthenticationAttribute : Attribute, IAuthenticationFilter { public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) { // 第一步:先将请求内容加载到内存缓冲,允许重复读取 await context.Request.Content.LoadIntoBufferAsync(); // 第二步:读取请求体内容计算HMAC哈希 string requestBody = await context.Request.Content.ReadAsStringAsync(); string computedSignature = 你的HMAC计算方法(requestBody, 密钥); // 第三步:执行签名校验逻辑,校验通过才继续执行后续流程 if (computedSignature != context.Request.Headers.GetValues("你的签名字段").FirstOrDefault()) { context.ErrorResult = new StatusCodeResult(HttpStatusCode.Unauthorized, context.Request); return; } // 注意:如果是直接读Stream的方式计算哈希,读完后需要手动把流位置重置为0 // var stream = await context.Request.Content.ReadAsStreamAsync(); // // 读流计算哈希的逻辑... // stream.Position = 0; } public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) { // 你的挑战逻辑 return Task.CompletedTask; } }
如果修改后还是有问题,可以检查你的HMAC逻辑中是否有替换context.Request.Content对象、修改Content-Type头的操作,这类操作也会导致后续模型绑定失败。
内容的提问来源于stack exchange,提问作者Tawm
相关产品推荐
相关产品推荐

