【发布时间】:2026-01-28 18:10:01
【问题描述】:
我正在实现一个自定义 owin 中间件,以在响应标头中添加 CSP 标头(内容安全策略)。要使CSP 正常工作,中间件需要为每个请求创建一个唯一的 nonce 值。所以我有NonceService,它创造了随机值。自定义 OWIN 中间件依赖于 NonceService。
但是我的问题是我无法为每个请求注册自定义中间件。
当我调试时,我注意到 OWIN 不为每个请求创建自定义中间件的新实例,因为所有请求都使用相同的 nonce 值。
下面是我的代码
Nonce 服务
public interface INonceService
{
string GetNonce();
}
public class NonceService : INonceService
{
private static readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
private readonly string _nonce;
public NonceService(int nonceByteAmount = 32)
{
var nonceBytes = new byte[nonceByteAmount];
_rng.GetBytes(nonceBytes);
_nonce = Convert.ToBase64String(nonceBytes);
}
public string GetNonce()
{
return _nonce;
}
}
OWIN 中间件和扩展
public class SecurityHeaderMiddleware : OwinMiddleware
{
private readonly INonceService _nonceService = null;
public SecurityHeaderMiddleware(OwinMiddleware next, INonceService nonceService) : base(next)
{
_nonceService = nonceService;
}
public override async Task Invoke(IOwinContext context)
{
await Next.Invoke(context);
var nonce = _nonceService.GetNonce();
var csp = BuildCSPHeader(nonce);
context.Response.Headers.Add(key, csp);
}
}
public static class OwinExtensions
{
private const string SecurityHeaderRegistrationKey = "SecurityHeaders";
public static IAppBuilder UseSecurityHeader(this IAppBuilder app, INonceService nonceService)
{
if (app == null)
throw new ArgumentNullException("app");
if (app.Properties.ContainsKey(SecurityHeaderRegistrationKey))
return app;
app.Use<SecurityHeaderMiddleware>(nonceService);
app.Properties.Add(SecurityHeaderRegistrationKey, true);
return app;
}
}
我使用 Unity 作为容器,所以我使用 PerRequestLifetimeManager 注册 INonceService
container.RegisterType<INonceService, NonceService>(new PerRequestLifetimeManager(), new InjectionConstructor(32));
我在 startup.cs 中向 OWIN 注册了我的自定义中间件
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var nonceService = ServiceLocator.Current.GetInstance<INonceService>();
app.UseSecurityHeader(nonceService);
}
}
注意 如果无法按请求创建 OWIN 中间件,那么至少我应该如何将每个请求的新 NonceService 实例传递给中间件。
【问题讨论】:
标签: asp.net-mvc asp.net-mvc-5 owin unity-container owin-middleware