如何在ASP.NET中间件中识别XssSanitizeIgnore自定义属性
解决文件上传场景下跳过XSS清理的问题
要在中间件中动态检测控制器或动作方法上的XssSanitizeIgnore属性,你需要通过当前请求的Endpoint对象获取对应的控制器和动作元数据,而非硬编码指定控制器类型。具体实现如下:
1. 修改中间件逻辑,添加属性检测
在中间件中先判断当前请求是否需要跳过XSS清理,再执行对应的逻辑。修改后的代码如下:
// 启用请求缓冲,确保后续模型绑定器能读取请求内容 httpContext.Request.EnableBuffering(); // 标记是否需要跳过XSS清理 var shouldSkipSanitize = false; var endpoint = httpContext.GetEndpoint(); if (endpoint != null) { // 检查端点元数据、控制器类、动作方法上是否存在XssSanitizeIgnore属性 shouldSkipSanitize = endpoint.Metadata.GetMetadata<XssSanitizeIgnore>() != null || endpoint.Metadata.GetMetadata<ControllerActionDescriptor>()?.ControllerTypeInfo.GetCustomAttribute<XssSanitizeIgnore>() != null || endpoint.Metadata.GetMetadata<ControllerActionDescriptor>()?.MethodInfo.GetCustomAttribute<XssSanitizeIgnore>() != null; } // 仅在不需要跳过的情况下执行XSS校验 if (!shouldSkipSanitize) { using (var streamReader = new StreamReader(httpContext.Request.Body, Encoding.UTF8, leaveOpen: true)) { var raw = await streamReader.ReadToEndAsync(); var sanitiser = new HtmlSanitizer(); var sanitised = sanitiser.Sanitize(raw); if (raw != sanitised) { throw new BadRequestException("XSS injection detected from middleware."); } } } // 重置请求流位置,供后续中间件使用 httpContext.Request.Body.Seek(0, SeekOrigin.Begin); await _next.Invoke(httpContext);
2. 优化属性定义(可选)
为了让属性的适用范围更清晰,可以修改XssSanitizeIgnore的定义,明确指定仅作用于控制器类和动作方法:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class XssSanitizeIgnore : Attribute { }
逻辑说明
- 通过
httpContext.GetEndpoint()获取当前请求匹配的端点信息,这是ASP.NET Core中获取请求对应控制器/动作的标准方式。 - 多维度检查属性:覆盖端点元数据、控制器类、动作方法三个层级,确保无论是标记在整个控制器还是单个动作上都能生效。
- 文件上传的
ProcessUploadedFile动作因标记了XssSanitizeIgnore,会直接跳过XSS清理逻辑,解决原有方案的适配问题。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

