-
Notifications
You must be signed in to change notification settings - Fork 84
Adds Https Redirection and Hsts Middlewares #264
Changes from 9 commits
d9f364d
18d6c96
9d3c8b2
4d27202
4a9495e
e9a1f5a
82401ac
e38ac6e
8c11086
a588a98
3aa120c
f72cb24
a704d29
23412eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks> | ||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.HttpsPolicy\Microsoft.AspNetCore.HttpsPolicy.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"iisSettings": { | ||
"windowsAuthentication": false, | ||
"anonymousAuthentication": true, | ||
"iisExpress": { | ||
"applicationUrl": "http://localhost:31894/", | ||
"sslPort": 0 | ||
} | ||
}, | ||
"profiles": { | ||
"IIS Express": { | ||
"commandName": "IISExpress", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
}, | ||
"HttpsSample": { | ||
"commandName": "Project", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"applicationUrl": "http://localhost:31895/" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.HttpsPolicy; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace HttpsSample | ||
{ | ||
public class Startup | ||
{ | ||
// This method gets called by the runtime. Use this method to add services to the container. | ||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.Configure<HttpsRedirectionOptions>(options => { | ||
options.RedirectStatusCode = 301; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
options.TlsPort = 5001; | ||
}); | ||
|
||
services.Configure<HstsOptions>(options => | ||
{ | ||
options.MaxAge = 5000; | ||
options.Preload = true; | ||
options.IncludeSubDomains = true; | ||
}); | ||
} | ||
|
||
public void Configure(IApplicationBuilder app, IHostingEnvironment environment) | ||
{ | ||
if (!environment.IsDevelopment()) | ||
{ | ||
app.UseHsts(); | ||
} | ||
app.UseHttpsRedirection(); | ||
|
||
app.Run(async context => | ||
{ | ||
await context.Response.WriteAsync("Hello world!"); | ||
}); | ||
} | ||
|
||
// Entry point for the application. | ||
public static void Main(string[] args) | ||
{ | ||
var host = new WebHostBuilder() | ||
.UseKestrel( | ||
options => | ||
{ | ||
options.Listen(new IPEndPoint(IPAddress.Loopback, 5001), listenOptions => | ||
{ | ||
listenOptions.UseHttps("testCert.pfx", "testPassword"); | ||
}); | ||
options.Listen(new IPEndPoint(IPAddress.Loopback, 5000), listenOptions => | ||
{ | ||
}); | ||
}) | ||
.UseContentRoot(Directory.GetCurrentDirectory()) // for the cert file | ||
.UseStartup<Startup>() | ||
.Build(); | ||
|
||
host.Run(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.HttpsPolicy; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Microsoft.AspNetCore.Builder | ||
{ | ||
/// <summary> | ||
/// Extension methods for the HSTS middleware. | ||
/// </summary> | ||
public static class HstsBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Adds middleware for using HSTS, which adds the Strict-Transport-Security header. | ||
/// </summary> | ||
/// <param name="app">The <see cref="IApplicationBuilder"/> instance this method extends.</param> | ||
public static IApplicationBuilder UseHsts(this IApplicationBuilder app) | ||
{ | ||
if (app == null) | ||
{ | ||
throw new ArgumentNullException(nameof(app)); | ||
} | ||
|
||
return app.UseMiddleware<HstsMiddleware>(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Options; | ||
using Microsoft.Extensions.Primitives; | ||
using Microsoft.Net.Http.Headers; | ||
|
||
namespace Microsoft.AspNetCore.HttpsPolicy | ||
{ | ||
/// <summary> | ||
/// Enables HTTP Strict Transport Security (HSTS) | ||
/// See https://tools.ietf.org/html/rfc6797. | ||
/// </summary> | ||
public class HstsMiddleware | ||
{ | ||
private const string IncludeSubDomains = "; includeSubDomains"; | ||
private const string Preload = "; preload"; | ||
|
||
private readonly RequestDelegate _next; | ||
private readonly StringValues _strictTransportSecurityValue; | ||
|
||
/// <summary> | ||
/// Initialize the HSTS middleware. | ||
/// </summary> | ||
/// <param name="next"></param> | ||
/// <param name="options"></param> | ||
public HstsMiddleware(RequestDelegate next, IOptions<HstsOptions> options) | ||
{ | ||
if (next == null) | ||
{ | ||
throw new ArgumentNullException(nameof(next)); | ||
} | ||
|
||
if (options == null) | ||
{ | ||
throw new ArgumentNullException(nameof(options)); | ||
} | ||
|
||
_next = next; | ||
|
||
var hstsOptions = options.Value; | ||
var includeSubdomains = hstsOptions.IncludeSubDomains ? IncludeSubDomains : StringSegment.Empty; | ||
var preload = hstsOptions.Preload ? Preload : StringSegment.Empty; | ||
|
||
_strictTransportSecurityValue = new StringValues($"max-age={hstsOptions.MaxAge}{includeSubdomains}{preload}"); | ||
} | ||
|
||
/// <summary> | ||
/// Invoke the middleware. | ||
/// </summary> | ||
/// <param name="context">The <see cref="HttpContext"/>.</param> | ||
/// <returns></returns> | ||
public Task Invoke(HttpContext context) | ||
{ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've got a blank line here. |
||
if (context.Request.IsHttps) | ||
{ | ||
context.Response.Headers[HeaderNames.StrictTransportSecurity] = _strictTransportSecurityValue; | ||
} | ||
return _next(context); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have a blank line before the return statement. |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
|
||
namespace Microsoft.AspNetCore.HttpsPolicy | ||
{ | ||
/// <summary> | ||
/// Options for the Hsts Middleware | ||
/// </summary> | ||
public class HstsOptions | ||
{ | ||
/// <summary> | ||
/// Sets the max-age parameter of the Strict-Transport-Security header. | ||
/// </summary> | ||
/// <remarks> | ||
/// Max-age is required; defaults to one month (2592000 seconds). | ||
/// See: https://tools.ietf.org/html/rfc6797#section-6.1.1 | ||
/// </remarks> | ||
public int MaxAge { get; set; } = 2592000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a TimeSpan so people don't have to do the math themselves. |
||
|
||
/// <summary> | ||
/// Enables includeSubDomain parameter of the Strict-Transport-Security header. | ||
/// </summary> | ||
/// <remarks> | ||
/// See: https://tools.ietf.org/html/rfc6797#section-6.1.2 | ||
/// </remarks> | ||
public bool IncludeSubDomains { get; set; } | ||
|
||
/// <summary> | ||
/// Sets the preload parameter of the Strict-Transport-Security header. | ||
/// </summary> | ||
/// <remarks> | ||
/// Preload is not part of the RFC specification, but is supported by web browsers | ||
/// to preload HSTS sites on fresh install. See https://hstspreload.org/. | ||
/// </remarks> | ||
public bool Preload { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Microsoft.AspNetCore.HttpsPolicy | ||
{ | ||
public static class HstsServicesExtensions | ||
{ | ||
public static IServiceCollection AddHsts(this IServiceCollection services, Action<HstsOptions> configureOptions) | ||
{ | ||
if (services == null) | ||
{ | ||
throw new ArgumentNullException(nameof(services)); | ||
} | ||
if (configureOptions == null) | ||
{ | ||
throw new ArgumentNullException(nameof(configureOptions)); | ||
} | ||
|
||
services.Configure(configureOptions); | ||
return services; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.HttpsPolicy; | ||
using Microsoft.AspNetCore.Rewrite; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Microsoft.AspNetCore.Builder | ||
{ | ||
/// <summary> | ||
/// Extension methods for the HttpsPolicy middleware. | ||
/// </summary> | ||
public static class HttpsPolicyBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Adds middleware for enforcing HTTPS for all HTTP Requests, including redirecting HTTP to HTTPS | ||
/// and adding the HTTP Strict-Transport-Header. | ||
/// </summary> | ||
/// <param name="app">The <see cref="IApplicationBuilder"/> instance this method extends.</param> | ||
/// <returns>The <see cref="IApplicationBuilder"/> with HttpsPolicy.</returns> | ||
/// <remarks> | ||
/// HTTPS Enforcement interanlly uses the UrlRewrite middleware to redirect HTTP requests to HTTPS | ||
/// </remarks> | ||
public static IApplicationBuilder UseHttpsRedirection(this IApplicationBuilder app) | ||
{ | ||
if (app == null) | ||
{ | ||
throw new ArgumentNullException(nameof(app)); | ||
} | ||
|
||
var options = app.ApplicationServices.GetRequiredService<IOptions<HttpsRedirectionOptions>>().Value; | ||
|
||
var rewriteOptions = new RewriteOptions(); | ||
rewriteOptions.AddRedirectToHttps( | ||
options.RedirectStatusCode, | ||
options.TlsPort); | ||
|
||
app.UseRewriter(rewriteOptions); | ||
|
||
return app; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace Microsoft.AspNetCore.HttpsPolicy | ||
{ | ||
/// <summary> | ||
/// Options for the HttpsRedirection middleware | ||
/// </summary> | ||
public class HttpsRedirectionOptions | ||
{ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extra line |
||
/// <summary> | ||
/// The status code to redirect the response to. | ||
/// </summary> | ||
public int RedirectStatusCode { get; set; } = StatusCodes.Status301MovedPermanently; | ||
|
||
/// <summary> | ||
/// The TLS port to be added to the redirected URL. | ||
/// </summary> | ||
/// <remarks> | ||
/// Defaults to 443 if not provided. | ||
/// </remarks> | ||
public int? TlsPort { get; set; } | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the samples to use the helper methods