CSP
応答ヘッダーにヘッダー (コンテンツ セキュリティ ポリシー)を追加するカスタム owin ミドルウェアを実装しています。が機能するにはCSP
、ミドルウェアがリクエストごとに一意の nonce 値を作成する必要があります。だから私はNonceService
ナンス値を作成するものを持っています。カスタム OWIN ミドルウェアは、NonceService に依存しています。
ただし、私の問題は、リクエストごとにカスタム ミドルウェアを登録できないことです。
デバッグすると、OWIN がリクエストごとにカスタム ミドルウェアの新しいインスタンスを作成していないことに気付きました。そのため、同じナンス値がすべてのリクエストに使用されています。
以下は私のコードです
ナンスサービス
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を使用しているので、INonceServiceを使用して登録しますPerRequestLifetimeManager
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 の新しいインスタンスをミドルウェアに渡す方法を教えてください。