Перенаправление на 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);
}
}
}
Ответы
Ответ 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-адреса приложения.
![введите описание изображения здесь]()
- Запустите приложение. Он всегда будет работать в контексте 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
{
}