mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-26 20:16:15 +08:00
Adding the ability to enable HTTP Strict Transport Security from the SSL module, fixes #6612
This commit is contained in:
@@ -30,6 +30,9 @@ namespace Orchard.SecureSocketsLayer.Drivers {
|
||||
protected override DriverResult Editor(SslSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
if (updater.TryUpdateModel(part, Prefix, null, null)) {
|
||||
_signals.Trigger(SslSettingsPart.CacheKey);
|
||||
if (!part.Enabled) part.SecureEverything = false;
|
||||
if (!part.SecureEverything) part.SendStrictTransportSecurityHeaders = false;
|
||||
if (!part.StrictTransportSecurityIncludeSubdomains) part.StrictTransportSecurityPreload = false;
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace Orchard.SecureSocketsLayer.Models {
|
||||
public class SslSettingsPart : ContentPart {
|
||||
public const string CacheKey = "SslSettingsPart";
|
||||
|
||||
public string Urls
|
||||
{
|
||||
public string Urls {
|
||||
get { return this.As<InfosetPart>().Get<SslSettingsPart>("Urls"); }
|
||||
set { this.As<InfosetPart>().Set<SslSettingsPart>("Urls", value); }
|
||||
}
|
||||
@@ -57,5 +56,26 @@ namespace Orchard.SecureSocketsLayer.Models {
|
||||
get { return this.As<InfosetPart>().Get<SslSettingsPart>("InsecureHostName"); }
|
||||
set { this.As<InfosetPart>().Set<SslSettingsPart>("InsecureHostName", value); }
|
||||
}
|
||||
|
||||
public bool SendStrictTransportSecurityHeaders {
|
||||
get { return this.Retrieve(x => x.SendStrictTransportSecurityHeaders); }
|
||||
set { this.Store(x => x.SendStrictTransportSecurityHeaders, value); }
|
||||
}
|
||||
|
||||
public bool StrictTransportSecurityIncludeSubdomains {
|
||||
get { return this.Retrieve(x => x.StrictTransportSecurityIncludeSubdomains); }
|
||||
set { this.Store(x => x.StrictTransportSecurityIncludeSubdomains, value); }
|
||||
}
|
||||
|
||||
[Required]
|
||||
public int StrictTransportSecurityMaxAge {
|
||||
get { return this.Retrieve(x => x.StrictTransportSecurityMaxAge, 31536000); }
|
||||
set { this.Store(x => x.StrictTransportSecurityMaxAge, value); }
|
||||
}
|
||||
|
||||
public bool StrictTransportSecurityPreload {
|
||||
get { return this.Retrieve(x => x.StrictTransportSecurityPreload); }
|
||||
set { this.Store(x => x.StrictTransportSecurityPreload, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,10 +49,18 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Owin, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||
@@ -96,6 +104,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\StrictTransportSecurityMiddlewareProvider.cs" />
|
||||
<Content Include="Module.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Owin;
|
||||
using Orchard.SecureSocketsLayer.Models;
|
||||
using Owin;
|
||||
|
||||
namespace Orchard.SecureSocketsLayer.Services {
|
||||
public class StrictTransportSecurityMiddlewareProvider : IOwinMiddlewareProvider {
|
||||
private readonly IWorkContextAccessor _wca;
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public StrictTransportSecurityMiddlewareProvider(IWorkContextAccessor wca) {
|
||||
_wca = wca;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public IEnumerable<OwinMiddlewareRegistration> GetOwinMiddlewares() {
|
||||
return new[] {
|
||||
new OwinMiddlewareRegistration {
|
||||
Configure = app =>
|
||||
app.Use(async (context, next) => {
|
||||
var sslSettings = _wca.GetContext().CurrentSite.As<SslSettingsPart>();
|
||||
|
||||
if (sslSettings.SendStrictTransportSecurityHeaders) {
|
||||
string responseValue = "max-age=" + sslSettings.StrictTransportSecurityMaxAge;
|
||||
|
||||
if (sslSettings.StrictTransportSecurityIncludeSubdomains) {
|
||||
responseValue += "; includeSubDomains";
|
||||
}
|
||||
|
||||
if (sslSettings.StrictTransportSecurityPreload) {
|
||||
responseValue += "; preload";
|
||||
}
|
||||
context.Response.Headers.Append("Strict-Transport-Security", responseValue);
|
||||
}
|
||||
|
||||
await next.Invoke();
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,18 +11,47 @@
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.SecureHostName)">@T("Secure Host Name")</label>
|
||||
@Html.TextBoxFor(m => m.SecureHostName, new { @class = "textMedium" })
|
||||
<span class="hint">@T("(Mandatory) The host name secured traffic should be redirected to (e.g. localhost:44300, secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333).")</span>
|
||||
@Html.Hint(T("(Mandatory) The host name secured traffic should be redirected to (e.g. localhost:44300, secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333)."))
|
||||
</div>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.InsecureHostName)">@T("Insecure Host Name")</label>
|
||||
@Html.TextBoxFor(m => m.InsecureHostName, new { @class = "textMedium" })
|
||||
<span class="hint">@T("(Mandatory) The host name non-secured traffic should be redirected to (e.g. localhost:30321, mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333).")</span>
|
||||
@Html.Hint(T("(Mandatory) The host name non-secured traffic should be redirected to (e.g. localhost:30321, mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333)."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.SecureEverything)
|
||||
<label for="@Html.FieldIdFor(m => m.SecureEverything)" class="forcheckbox">@T("Force SSL on all pages")</label>
|
||||
@Html.ValidationMessage("SecureEverything", "*")
|
||||
</div>
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.SecureEverything)">
|
||||
<div>
|
||||
@Html.EditorFor(m => m.SendStrictTransportSecurityHeaders)
|
||||
<label for="@Html.FieldIdFor(m => m.SendStrictTransportSecurityHeaders)" class="forcheckbox">@T("Enable HTTP Strict Transport Security")</label>
|
||||
@Html.Hint(@T("<a href='https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security' target='_blank'>More information about HSTS</a>"))
|
||||
@Html.ValidationMessage("SendStrictTransportSecurityHeaders", "*")
|
||||
</div>
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.SendStrictTransportSecurityHeaders)">
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.StrictTransportSecurityMaxAge)">@T("Expiration time")</label>
|
||||
@Html.TextBoxFor(m => m.StrictTransportSecurityMaxAge, new { @class = "textMedium" })
|
||||
@Html.Hint(T("(Mandatory) Specify the max age of HSTS in seconds (e.g. 31536000 is one year). If you set this parameter to 0, the HSTS Header will immediately expire."))
|
||||
</div>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.StrictTransportSecurityIncludeSubdomains)
|
||||
<label for="@Html.FieldIdFor(m => m.StrictTransportSecurityIncludeSubdomains)" class="forcheckbox">@T("Include Subdomains")</label>
|
||||
@Html.ValidationMessage("StrictTransportSecurityIncludeSubdomains", "*")
|
||||
@Html.Hint(T("Applies the HSTS rules to all of the site's subdomains."))
|
||||
</div>
|
||||
<div data-controllerid="@Html.FieldIdFor(m => m.StrictTransportSecurityIncludeSubdomains)">
|
||||
<div>
|
||||
@Html.EditorFor(m => m.StrictTransportSecurityPreload)
|
||||
<label for="@Html.FieldIdFor(m => m.StrictTransportSecurityPreload)" class="forcheckbox">@T("Preload")</label>
|
||||
@Html.ValidationMessage("StrictTransportSecurityPreload", "*")
|
||||
@Html.Hint(T("You can use this if you successfully submitted your domain to an HSTS preload service and serve all subdomains over HTTPS. If you send this directive, it can have PERMANENT CONSEQUENCES. Please read the <a href='https://hstspreload.appspot.com/' target='_blank'>details</a> before sending the header with \"preload\"."))
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
@Html.EditorFor(m => m.CustomEnabled)
|
||||
@@ -34,11 +63,10 @@
|
||||
<label for="@Html.FieldIdFor(m => m.Urls)">@T("Urls")</label>
|
||||
@Html.TextAreaFor(m => m.Urls, new { @class = "textMedium", rows = "5" })
|
||||
@Html.ValidationMessage("Urls", "*")
|
||||
<span class="hint">@T("Provide a list of urls, one per line. Urls can contains wildcard matches using '*', or root identifier like '~/'")</span>
|
||||
<span class="hint">@T("Examples: http://mysite.com/mypage, ~/Profile/Edit, ~/Profile/*")</span>
|
||||
@Html.Hint(T("Provide a list of urls, one per line. Urls can contains wildcard matches using '*', or root identifier like '~/'"))
|
||||
@Html.Hint(T("Examples: http://mysite.com/mypage, ~/Profile/Edit, ~/Profile/*"))
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net452" />
|
||||
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net452" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
|
||||
<package id="Owin" version="1.0" targetFramework="net452" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user