重定向到HTTPS

时间:2015-04-06 18:39:07

标签: c# redirect https asp.net-core middleware

将所有不安全的传入请求重定向到HTTPS的建议方法是什么?我是否需要编写中间件组件?如果是这样,我无法弄清楚如何获取服务器名称。

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);
        }
    }
}

11 个答案:

答案 0 :(得分:43)

您可以使用自己的中间件类,但通常我只是在我的启动配置中执行类似的操作:

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);
    }
});

这样做只是抓取整个网址,查询字符串和所有内容,并使用GetComponents获取除了网址中的方案。然后,HTTPS方案将被添加到组件URL。

这将适用于完整的.NET Framework,对于ASP.NET Core,您可以执行以下操作:

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);
    }
});

这会将主机和路径附加到HTTPS方案。您可能还想添加其他组件,例如查询和哈希。

答案 1 :(得分:16)

对于.NET Core 2.0及更低版本(official docs for 2.0):

使用[RequireHttps]属性/过滤器。 您可以对控制器执行此操作:

[RequireHttps]
public class AccountController {
}

或者在Startup.cs方法的ConfigureServices中添加此内容:

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

另外,我只想添加vcsjones&#39;答案也是正确的,但您需要确保在配置中尽早添加此代码,然后再导致导致重定向的任何其他中间件/代码。就我而言,我在添加Identity Framework中间件之前添加了它。

答案 2 :(得分:12)

完整答案排在第1位但不要停止设置HTTPS,请采取额外步骤:

1 - 然后我们使用RequireHttpsAttribute重定向到HTTPS并在MVC选项中设置SSL端口。我们也在从launchSettings.json读取SSL端口,但我们只需要在开发模式下使用它。

2 - 使用AddAntiforgery要求在防伪令牌上使用HTTPS。

3 - 使用NWebsec.AspNetCore.Middleware NuGet包和UseHsts方法在整个站点启用严格传输安全(HSTS)。不要忘记在下面添加预加载并将您的网站提交到HSTS Preload site。更多信息herehere

4 - 使用NWebsec.AspNetCore.Middleware NuGet包和UseHpkp方法在网站上启用公钥固定(HPKP)。请注意,如果您在使用本网站时出错,那么您基本上就是自己的网站。更多信息herehere

5 - 在所使用的任何网址中加入https计划。当您在某些浏览器中模仿该方案时,Content Security Policy (CSP) HTTP标头和Subresource Integrity (SRI)不会很好用。最好明确HTTPS。 e.g。

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

6-使用ASP.NET MVC Boilerplate Visual Studio项目模板生成一个包含所有这些内置项目的项目。您还可以在GitHub上查看代码。

完成上述所有操作后,您的Startup课程应如下所示:

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();
    }
}

答案 3 :(得分:3)

如果您想在.NET Core中的DEV环境中获取端口,请查看env.IsDevelopment()并有条件地从launchSettings.json获取SSL端口。

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");
}

`

在抓取SSL端口之后,您可以将端口合并到@vcsjones发布的解决方案中。

答案 4 :(得分:2)

我已经修改了一些@vcsjones的答案,以便在开发环境中使用自定义端口。也归功于@ 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);
    }
});

这必须出现在app.UseStaticFiles或app.UseMvc之前,否则将被忽略。

请注意,该端口应取自launchSettings.json文件,因此您还应将此文件添加到ConfigurationBuilder中的Startup.cs

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

答案 5 :(得分:2)

AlwaysHttpsMiddleware.cs,inspired by 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>();
    }
 }

答案 6 :(得分:1)

在ASP.NET Core 2.1中只需使用以下内容:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();   // <-- Add this !!!!!
    }

    app.UseHttpsRedirection(); // <-- Add this !!!!!
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

答案 7 :(得分:0)

这里有一些很好的答案,但我需要一个可以使用或不使用IIS的解决方案,也不需要在本地调试期间更改协议。我在Startup.Configure方法中将AD auth添加到管道后添加了这个。这是完整的框架。此处的其他解决方案概述了如何重建Core的URL。

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);
    }
});

答案 8 :(得分:0)

为了让您的DOTNet Core应用程序在HTTPS下运行,需要遵循以下三个步骤:

  1. 导航到您的应用程序的launchSettings.json文件,然后从44390-44399输入您想要的https端口 enter image description here
  2. 编辑您的Startup.cs文件。输入以下代码:

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

    enter image description here

  3. 右键单击“项目根目录”,从“解决方案资源管理器”中选择“属性”。选中启用SSL,复制SSL链接并将其添加到应用URL区域。 enter image description here

    1. 启动应用程序。它将始终在HTTPS上下文中运行。

答案 9 :(得分:0)

https://github.com/aspnet/KestrelHttpServer/issues/916讨论的一种技术是将其添加到您的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>

答案 10 :(得分:-1)

我喜欢编译器指令

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