useurls usekestrel usehttpsredirection usehsts only net kestrelserveroptions dotnet dev configured certs asp app c# redirect https asp.net-core middleware

c# - usekestrel - Redirigir a HTTPS



usekestrel net core (10)

¿Cuál es la forma recomendada de redirigir a HTTPS todas las solicitudes entrantes que no son seguras? ¿Necesito escribir un componente de middleware? Si es así, no podría encontrar la forma de obtener el nombre del servidor.

public class RedirectHttpMiddleware { RequestDelegate _next; public RedirectHttpMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (context.Request.IsSecure) await _next(context); else { var server = ""; // How do I get the server name? context.Response.Redirect("https://" + server + context.Request.Path); } } }


AlwaysHttpsMiddleware.cs, inspirado en RequiresHttpsAttribute.

using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; public class AlwaysHttpsMiddleware { private readonly RequestDelegate _next; public AlwaysHttpsMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (context.Request.IsHttps) { await _next.Invoke(context); } else { var request = context.Request; // only redirect for GET requests, otherwise the browser might // not propagate the verb and request body correctly. if (!string.Equals(request.Method, "GET", StringComparison.OrdinalIgnoreCase)) { context.Response.StatusCode = StatusCodes.Status403Forbidden; await context.Response.WriteAsync("This site requires HTTPS."); } else { var newUrl = string.Concat( "https://", request.Host.ToUriComponent(), request.PathBase.ToUriComponent(), request.Path.ToUriComponent(), request.QueryString.ToUriComponent()); context.Response.Redirect(newUrl); } } } }

Startup.cs

public void Configure(IApplicationBuilder app) { if (_env.IsProduction()) { app.UseMiddleware<AlwaysHttpsMiddleware>(); } }


Aquí hay algunas respuestas excelentes, pero necesitaba una solución que funcionara con o sin IIS y tampoco cambiara el protocolo durante la depuración local. Añadí esto justo después de agregar AD auth a la canalización en el método Startup.Configure. Esto es para el marco completo. Otras soluciones aquí describen cómo reconstruir la URL para Core.

app.Use(async (context, next) => { if (context.Request.IsHttps || // Handles https straight to the server context.Request.Headers["X-Forwarded-Proto"] == Uri.UriSchemeHttps || // Handles an IIS or Azure passthrough context.Request.Host.ToString().StartsWith("localhost",true, System.Globalization.CultureInfo.InvariantCulture) || // Ignore for localhost context.Request.Headers["X-Forwarded-Proto"].Contains( Uri.UriSchemeHttps )) // X-Forwarded-Proto can have multiple values if there are multiple proxies { await next(); } else { var withHttps = Uri.UriSchemeHttps + Uri.SchemeDelimiter + context.Request.Host + context.Request.Path + context.Request.QueryString; context.Response.Redirect(withHttps); } });


He modificado un poco la respuesta de @vcsjones para usar un puerto personalizado en el entorno de desarrollo. También créditos a @ long2know.

app.Use(async (context, next) => { var request = context.Request; if (request.IsHttps) { await next(); } else { var devPort = Configuration.GetValue<int>("iisSettings:iisExpress:sslPort"); var host = env.IsDevelopment() && devPort > 0 ? new HostString(request.Host.Host, devPort) : new HostString(request.Host.Host); string newUrl = $"https://{host}{request.PathBase}{request.Path}{request.QueryString}"; context.Response.Redirect(newUrl, true); } });

Esto debe aparecer antes de app.UseStaticFiles o app.UseMvc; de lo contrario, se ignorará.

Tenga en cuenta que el puerto debe tomarse del archivo launchSettings.json , por lo que también debe agregar este archivo a ConfigurationBuilder en Startup.cs :

.AddJsonFile(@"Properties/launchSettings.json", optional: false, reloadOnChange: true)


La respuesta completa está en el número 1, pero no se detenga allí configurando HTTPS, vaya al paso adicional:

1 - Luego usamos RequireHttpsAttribute para redirigir a HTTPS y configuramos el puerto SSL en las opciones de MVC. También estamos leyendo el puerto SSL de launchSettings.json, pero solo necesitamos esto en modo Desarrollo.

2 - Use AddAntiforgery para requerir HTTPS en sus tokens AddAntiforgery .

3 - Use el paquete NWebsec.AspNetCore.Middleware NWebsec.AspNetCore.Middleware y el método UseHsts para habilitar la Seguridad de transporte estricta (HSTS) en todo el sitio. No olvide agregar la Precarga a continuación y enviar su sitio al sitio de Precarga de HSTS . Más información here y here .

4 - Use el paquete NWebsec.AspNetCore.Middleware NWebsec.AspNetCore.Middleware y el método UseHpkp para habilitar la UseHpkp de clave pública (HPKP) en todo el sitio. Tenga en cuenta que si comete un error con este, esencialmente está haciendo su sitio. Más información here y here .

5 - Incluye el esquema https en cualquier URL utilizada. Content Security Policy (CSP) El encabezado HTTP y Subresource Integrity (SRI) no funcionan bien cuando se imita el esquema en algunos navegadores. Es mejor ser explícito sobre HTTPS. p.ej

<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/bootstrap.min.js"></script>

6- Utilice la plantilla de proyecto Visual Studio ASP.NET MVC Boilerplate para generar un proyecto con todo esto y mucho más incorporado. También puede ver el código en GitHub .

Después de todo lo anterior, tu clase de Startup debería verse más o menos así:

public class Startup { private readonly int? sslPort; public Startup(IHostingEnvironment hostingEnvironment) { if (hostingEnvironment.IsDevelopment()) { var launchConfiguration = new ConfigurationBuilder() .SetBasePath(hostingEnvironment.ContentRootPath) .AddJsonFile(@"Properties/launchSettings.json") .Build(); // During development we won''t be using port 443. this.sslPort = launchConfiguration.GetValue<int>("iisSettings:iisExpress:sslPort"); } } public void ConfigureServices(IServiceCollection services) { services .AddAntiforgery(options => { options.RequireSsl = true; }); .AddMvc(options => { options.Filters.Add(new RequireHttpsAttribute()); options.SslPort = sslPort; }); } public void Configure(IApplicationBuilder application) { application .UseHsts(options => options.MaxAge(days: 18 * 7).IncludeSubdomains().Preload()) .UseHpkp(options => options .Sha256Pins( "Base64 encoded SHA-256 hash of your first certificate e.g. cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=", "Base64 encoded SHA-256 hash of your second backup certificate e.g. M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=") .MaxAge(days: 18 * 7) .IncludeSubdomains()) .UseCsp(options => options .UpgradeInsecureRequests(this.sslPort.HasValue ? this.sslPort.Value : 443)) .UseMvc(); } }


Me gusta el atributo con la directiva del compilador

#if !DEBUG [RequireHttps] #endif public class HomeController : Controller { }


Otra forma que prefiero es usar el atributo / filtro [RequireHttps]. Usted puede hacer esto a sus controladores:

[RequireHttps] public class AccountController { }

O bien, esto en su Startup.cs en ConfigureServices:

services.Configure<MvcOptions>(options => { options.Filters.Add(new RequireHttpsAttribute()); }

Además, solo quería agregar que la respuesta de vcsjones también es correcta, pero debe asegurarse de agregar este código desde el principio en su configuración, antes de cualquier otro Middleware / código que cause redirecciones. En mi caso, lo agregué justo antes de agregar el middleware de Identity Framework.


Para que su aplicación DOTNet Core se ejecute bajo HTTPS, hay tres pasos a seguir:

  1. Navegue hasta el archivo launchSettings.json de su Aplicación e ingrese su puerto https deseado desde 44390-44399
  2. Edite su archivo Startup.cs. Ingrese el siguiente código:

    services.Configure<MvcOptions>(options => { options.SslPort = 44390; options.Filters.Add(new RequireHttpsAttribute()); });

  3. Haga clic con el botón derecho en su Directorio raíz del proyecto, desde el Explorador de soluciones y Seleccionar propiedades. Seleccione Habilitar SSL, copie el enlace SSL y agréguelo al área URL de la aplicación.

    1. Iniciar la aplicacion. Siempre se ejecutará en el contexto HTTPS.

Puede usar su propia clase de middleware, pero normalmente solo hago algo como esto en mi configuración de inicio:

app.Use(async (context, next) => { if (context.Request.IsHttps) { await next(); } else { var withHttps = Uri.UriSchemeHttps + Uri.SchemeDelimiter + context.Request.Uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Scheme, UriFormat.SafeUnescaped); context.Response.Redirect(withHttps); } });

Lo que hace es capturar toda la URL, cadena de consulta y todo, y usar GetComponents para obtener todo, excepto el esquema en la URL. Luego, el esquema HTTPS se antepone a la URL de los componentes.

Esto funcionará con .NET Framework completo, para ASP.NET Core, puede hacer algo como esto:

app.Use(async (context, next) => { if (context.Request.IsHttps) { await next(); } else { var withHttps = "https://" + context.Request.Host + context.Request.Path; context.Response.Redirect(withHttps); } });

Esto agrega el host y la ruta al esquema HTTPS. Es posible que desee agregar otros componentes, como la consulta y el hash, también.


Si desea tomar el puerto cuando se encuentre en un entorno DEV en .NET Core, mire env.IsDevelopment() y env.IsDevelopment() condicionalmente el puerto SSL de launchSettings.json .

if (env.IsDevelopment()) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile(@"Properties/launchSettings.json", optional: false, reloadOnChange: true); var launchConfig = builder.Build(); sslPort = launchConfig.GetValue<int>("iisSettings:iisExpress:sslPort"); }

`

Después de grabing el puerto SSL, puede incorporar el puerto en la solución publicada por @vcsjones.


Una técnica discutida en https://github.com/aspnet/KestrelHttpServer/issues/916 es agregar esto a su web.config:

<rewrite> <rules> <rule name="HTTP/S to HTTPS Redirect" enabled="true" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAny"> <add input="{SERVER_PORT_SECURE}" pattern="^0$" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule> </rules> </rewrite>