diff --git a/src/OwaspHeaders.Core.csproj b/src/OwaspHeaders.Core.csproj index c59532a..a6dbafd 100644 --- a/src/OwaspHeaders.Core.csproj +++ b/src/OwaspHeaders.Core.csproj @@ -8,13 +8,13 @@ OwaspHeaders.Core - 9.6.1 + 9.6.2 Jamie Taylor RJJ Software Ltd MIT Copyright (c) Jamie Taylor / RJJ Software Ltd owasp http headers security - An ASP.NET Core Middleware which adds the OWASP recommended HTTP headers for enhanced security. + An ASP.NET Core Middleware which adds the OWASP recommended HTTP headers, with a single line of code, for enhanced security. icon.png README-NuGet.md https://gaprogman.github.io/OwaspHeaders.Core/ diff --git a/src/SecureHeadersMiddleware.cs b/src/SecureHeadersMiddleware.cs index 94e1dca..0b93cd6 100644 --- a/src/SecureHeadersMiddleware.cs +++ b/src/SecureHeadersMiddleware.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Frozen; +using System.Linq; using System.Threading.Tasks; namespace OwaspHeaders.Core; @@ -9,8 +10,7 @@ namespace OwaspHeaders.Core; /// public class SecureHeadersMiddleware { - private string _calculatedContentSecurityPolicy; - private readonly Dictionary _headers; + private FrozenDictionary _headers; private readonly RequestDelegate _next; private readonly SecureHeadersMiddlewareConfiguration _config; @@ -18,7 +18,7 @@ public SecureHeadersMiddleware(RequestDelegate next, SecureHeadersMiddlewareConf { _config = config; _next = next; - _headers = new Dictionary(); + _headers = FrozenDictionary.Empty; } /// @@ -39,7 +39,7 @@ public async Task InvokeAsync(HttpContext httpContext) { if (_headers.Count == 0) { - GenerateRelevantHeaders(); + _headers = GenerateRelevantHeaders(); } foreach (var (key, value) in _headers) @@ -52,88 +52,81 @@ public async Task InvokeAsync(HttpContext httpContext) await _next(httpContext); } - private void GenerateRelevantHeaders() + private FrozenDictionary GenerateRelevantHeaders() { + var temporaryDictionary = new Dictionary(); + if (_config.UseHsts) { - _headers.TryAdd(Constants.StrictTransportSecurityHeaderName, + temporaryDictionary.Add(Constants.StrictTransportSecurityHeaderName, _config.HstsConfiguration.BuildHeaderValue()); } if (_config.UseXFrameOptions) { - _headers.TryAdd(Constants.XFrameOptionsHeaderName, + temporaryDictionary.Add(Constants.XFrameOptionsHeaderName, _config.XFrameOptionsConfiguration.BuildHeaderValue()); } if (_config.UseXssProtection) { - _headers.TryAdd(Constants.XssProtectionHeaderName, + temporaryDictionary.Add(Constants.XssProtectionHeaderName, _config.XssConfiguration.BuildHeaderValue()); } if (_config.UseXContentTypeOptions) { - _headers.TryAdd(Constants.XContentTypeOptionsHeaderName, Constants.XContentTypeOptionsValue); + temporaryDictionary.Add(Constants.XContentTypeOptionsHeaderName, Constants.XContentTypeOptionsValue); } if (_config.UseContentSecurityPolicyReportOnly) { - if (string.IsNullOrWhiteSpace(_calculatedContentSecurityPolicy)) - { - _calculatedContentSecurityPolicy = - _config.ContentSecurityPolicyReportOnlyConfiguration.BuildHeaderValue(); - } - - _headers.TryAdd(Constants.ContentSecurityPolicyReportOnlyHeaderName, - _calculatedContentSecurityPolicy); + temporaryDictionary.Add(Constants.ContentSecurityPolicyReportOnlyHeaderName, + _config.ContentSecurityPolicyReportOnlyConfiguration.BuildHeaderValue()); } else if (_config.UseContentSecurityPolicy) { - if (string.IsNullOrWhiteSpace(_calculatedContentSecurityPolicy)) - { - _calculatedContentSecurityPolicy = _config.ContentSecurityPolicyConfiguration.BuildHeaderValue(); - } - - _headers.TryAdd(Constants.ContentSecurityPolicyHeaderName, - _calculatedContentSecurityPolicy); + temporaryDictionary.Add(Constants.ContentSecurityPolicyHeaderName, + _config.ContentSecurityPolicyConfiguration.BuildHeaderValue()); } if (_config.UseXContentSecurityPolicy) { - _headers.TryAdd(Constants.XContentSecurityPolicyHeaderName, + temporaryDictionary.Add(Constants.XContentSecurityPolicyHeaderName, _config.ContentSecurityPolicyConfiguration.BuildHeaderValue()); } if (_config.UsePermittedCrossDomainPolicy) { - _headers.TryAdd(Constants.PermittedCrossDomainPoliciesHeaderName, + temporaryDictionary.Add(Constants.PermittedCrossDomainPoliciesHeaderName, _config.PermittedCrossDomainPolicyConfiguration.BuildHeaderValue()); } if (_config.UseReferrerPolicy) { - _headers.TryAdd(Constants.ReferrerPolicyHeaderName, + temporaryDictionary.Add(Constants.ReferrerPolicyHeaderName, _config.ReferrerPolicy.BuildHeaderValue()); } if (_config.UseExpectCt) { - _headers.TryAdd(Constants.ExpectCtHeaderName, + temporaryDictionary.Add(Constants.ExpectCtHeaderName, _config.ExpectCt.BuildHeaderValue()); } if (_config.UseCacheControl) { - _headers.TryAdd(Constants.CacheControlHeaderName, + temporaryDictionary.Add(Constants.CacheControlHeaderName, _config.CacheControl.BuildHeaderValue()); } if (_config.UseCrossOriginResourcePolicy) { - _headers.TryAdd(Constants.CrossOriginResourcePolicyHeaderName, + temporaryDictionary.Add(Constants.CrossOriginResourcePolicyHeaderName, _config.CrossOriginResourcePolicy.BuildHeaderValue()); } + + return temporaryDictionary.ToFrozenDictionary(); } private bool RequestShouldBeIgnored(PathString requestedPath)