Подтвердить что ты не робот

Перенаправление на HTTPS

Каков рекомендуемый способ перенаправления 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);
        }
    }
}
4b9b3361

Ответ 1

Вы можете использовать свой собственный класс промежуточного программного обеспечения, но обычно я просто делаю что-то подобное в моей конфигурации запуска:

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

Что это значит, просто захватите весь URL, строку запроса и все, и используйте GetComponents, чтобы получить все, кроме схемы в URL. Затем схема HTTPS добавляется к URL-адресу компонентов.

Это будет работать с полной платформой .NET Framework для ядра ASP.NET, вы можете сделать что-то вроде этого:

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. Вы можете также добавить другие компоненты, такие как запрос и хеш.

Ответ 2

Другим способом, который я предпочитаю, является использование атрибута/фильтра [RequireHttps]. Вы можете либо сделать это для своих контроллеров:

[RequireHttps]
public class AccountController {
}

Или иначе это в вашем Startup.cs в ConfigureServices:

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

Кроме того, я просто хотел добавить, что ответ vcsjones также верен, но вы должны обязательно добавить этот код на раннем этапе в своей конфигурации перед любым другим промежуточным программным обеспечением/кодом, который вызывает перенаправления. В моем случае я добавил его непосредственно перед тем, как добавить промежуточное программное обеспечение Identity Framework.

Ответ 3

Полный ответ - в номере 1, но не останавливайте там настройку HTTPS, выполните дополнительный шаг:

1 - Затем мы используем RequireHttpsAttribute для перенаправления на HTTPS и установки порта SSL в параметрах MVC. Мы также читаем порт SSL из launchSettings.json, но нам это нужно только в режиме разработки.

2 - Используйте AddAntiforgery, чтобы потребовать HTTPS на ваших токенах подделки.

3 - Используйте пакет NWebsec.AspNetCore.Middleware NuGet и UseHsts, чтобы включить Strict Transport Security (HSTS) по всему сайту. Не забудьте добавить Preload ниже и отправить свой сайт на сайт HSTS Preload. Подробнее здесь и здесь.

4 - Используйте пакет NWebsec.AspNetCore.Middleware NuGet и метод UseHpkp, чтобы включить привязку открытого ключа (HPKP) по всему сайту. Обратите внимание, что если вы ошиблись с этим, вы, по сути, делаете DoS'ing своего сайта. Подробнее здесь и здесь.

5 - Включите схему https в любом используемом URL. Политика безопасности контента (CSP) Заголовок HTTP и Целостность субресурсов (SRI) не очень приятны, когда вы имитируете схемы в некоторых браузерах. Лучше говорить о HTTPS. например.

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

Ответ 4

Если вы хотите захватить порт, когда находитесь в среде DEV в .NET Core, посмотрите env.IsDevelopment() и условно захватите порт SSL из 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");
}

`

После захвата SSL-порта вы можете включить порт в решение, отправленное @vcsjones.

Ответ 5

AlwaysHttpsMiddleware.cs, вдохновленный 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

Я изменил бит @vcsjones на использование пользовательского порта в среде dev. Также кредиты @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()
            ? 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);
    }
});

Обратите внимание, что порт должен быть взят из файла launchSettings.json, поэтому вы также должны добавить этот файл в ConfigurationBuilder в Startup.cs:

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

Ответ 7

Здесь есть несколько отличных ответов, но мне нужно решение, которое будет работать с IIS или без него, а также не изменять протокол во время локальной отладки. Я добавил это сразу после добавления AD auth к конвейеру в методе Startup.Configure. Это для полной структуры. Другие решения здесь описывают, как перестроить 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

Чтобы ваше приложение DOTNet Core работало под HTTPS, необходимо выполнить следующие шаги:

  • Перейдите в файл приложения launchSettings.json и введите желаемый порт https с 44390-44399 введите описание изображения здесь
  • Отредактируйте файл Startup.cs. Введите следующий код:

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

    введите описание изображения здесь

  • Щелкните правой кнопкой мыши на своем корневом каталоге проекта, в обозревателе решений и выберите "Свойства". Установите флажок Включить SSL, Скопируйте ссылку SSL и добавьте ее в область URL-адреса приложения. введите описание изображения здесь

    1. Запустите приложение. Он всегда будет работать в контексте HTTPS.

Ответ 9

Один метод, обсуждаемый в 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

Мне нравится атрибут с директивой компилятора

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