如何根据请求创建 OWIN 中间件
Posted
技术标签:
【中文标题】如何根据请求创建 OWIN 中间件【英文标题】:How to create OWIN middleware per request 【发布时间】:2017-09-27 02:28:53 【问题描述】:我正在实现一个自定义 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 实例传递给中间件。
【问题讨论】:
【参考方案1】:查看我收到的HttpContext
的空引用异常时的堆栈跟踪,似乎中间件是在BuildWebHost
中从Main
构造的。
我也在使用 Unity,所以我将构造函数依赖项从...更改为...
IUserRepository userRepository
到
Func<IUserRepository> userRepositoryFactory
我的方法调用来自...
userRepository.FetchLoggedInUser(userIdentifier);
到
userRepositoryFactory().FetchLoggedInUser(userIdentifier);
方便,Unity 自动生成工厂,因此无需编辑注册。
【讨论】:
以上是关于如何根据请求创建 OWIN 中间件的主要内容,如果未能解决你的问题,请参考以下文章
修改 OWIN OAuth 中间件以使用 JWT 不记名令牌
Owin,在Authentication Request中传递自定义查询参数
如何将 Azure OpenIdConnect OWIN 中间件 Cookie Auth 转换为 SPA 应用程序的 JavaScript JWT?