Кращий спосіб на asp.net змусити https для всього сайту?


192

Близько 6 місяців тому я розгорнув сайт, де кожен запит повинен був бути над https. Єдиний спосіб, коли я міг переконатися, що кожен запит на сторінку перевищував https, - це перевірити його у події завантаження сторінки. Якщо запит не був над http, я б відповів.redirect (" https://example.com ")

Чи є кращий спосіб - в ідеалі деякі налаштування в web.config?


перевірити мою відповідь тут stackoverflow.com/questions/33882350/…
Шеді Шериф

Відповіді:


250

Будь ласка, використовуйте HSTS (сувора безпека транспорту HTTP)

від http://www.hanselman.com/blog/HowToEnableHTTPStrictTransportSecurityHSTSInIIS7.aspx

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}"
                        redirectType="Permanent" />
                </rule>
            </rules>
            <outboundRules>
                <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
                    <match serverVariable="RESPONSE_Strict_Transport_Security"
                        pattern=".*" />
                    <conditions>
                        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
                    </conditions>
                    <action type="Rewrite" value="max-age=31536000" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

Оригінальний відповідь (замінено вищезгаданим 4 грудня 2015 року)

в основному

protected void Application_BeginRequest(Object sender, EventArgs e)
{
   if (HttpContext.Current.Request.IsSecureConnection.Equals(false) && HttpContext.Current.Request.IsLocal.Equals(false))
   {
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
+   HttpContext.Current.Request.RawUrl);
   }
}

це було б у global.asax.cs (або global.asax.vb)

Я не знаю способу вказати це в web.config


7
Це працює, але для мене це було небезпечно: коли я намагався запустити локально в VS 2010 за допомогою цього коду, моя стартова сторінка ніколи не завантажувалася; натомість я щойно отримав повідомлення "Ця веб-сторінка недоступна". Щоб виправити, я додав другу умову, щоб перевірити, чи URL-адреса містить рядок "localhost": якщо цього немає, то примушуйте https.
mg1075

3
Це дає мені цикл перенаправлення. Перш ніж я додати код, він працював чудово. Будь-які пропозиції?
Джо

9
Зауважте, що це не забезпечує жодної корисної безпеки. Насправді він захищатиме лише з'єднання від користувачів, які вже захищені, і не зможе захистити тих, на кого напали (це тому, що MITM може просто взагалі опустити перенаправлення та переслати все на ваш "захищений" сайт). IMHO, перенаправлення користувальницьких агентів - це просто хороша безпека вуду та забезпечує інколи небезпечну ілюзію безпеки. Єдиний шлях - доручити агентам користувачів запитувати лише захищені ресурси, а не перенаправляти їх, якщо вони цього не роблять. Це те, що робить HSTS - див. Відповіді нижче.
tne

2
Цю відповідь слід вважати «шкідливою» і не використовувати її. Відповідно до коментаря @tne вище.
Росді Касім

2
@RosdiKasim Чи слід цю відповідь вважати шкідливою після редакції 4 грудня 15 року?
Ендрю Мортон

123

Інше, що ви можете зробити - це використовувати HSTS , повернувши в браузер заголовок "Строгий транспорт-безпека". Веб-переглядач повинен підтримувати це (і зараз це в першу чергу Chrome і Firefox), але це означає, що після встановлення браузер не надсилатиме запити на сайт через HTTP, а замість цього переводить їх на запити HTTPS перед тим, як видавати їх . Спробуйте це в поєднанні з переспрямуванням з HTTP:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
  switch (Request.Url.Scheme)
  {
    case "https":
      Response.AddHeader("Strict-Transport-Security", "max-age=300");
      break;
    case "http":
      var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", path);
      break;
  }
}

Веб-браузери, які не знають HSTS, просто ігнорують заголовок, але все-таки потраплять у заяву перемикання та надсилаються на HTTPS.


6
Ніколи не чув про заголовок HSTS раніше, але виглядає досить круто. Чи є якась причина використання такого невеликого значення максимального віку (5 хвилин)? Стаття у Вікіпедії, на яку ви посилаєтесь, пропонує встановити велику цінність (6-12 місяців).
дата

5
+1. перегляньте цю дуже обширну статтю в блозі Трої, яка містить детальну інформацію про те, чому лише використання переадресації може знизити безпеку. Підказка: він може залишати вас вразливим до інструменту SSL Strip, серед іншого. troyhunt.com/2011/11/…
Оран Деннісон

3
Також варто перевірити NWebsec , що робить це (і багато іншого) дуже простим.
Тієсон Т.

16
Ви хочете зафіксувати перемикач, if(!Request.IsLocal)щоб він не зламав налагодження.
Джастін Дж. Старк

1
Хороша відповідь. Одна тонкість - для заголовків Http ("Strict-Transport-Security") краще використовувати бібліотеку типу NWebSec, оскільки є кілька варіантів, які сконцентровані в одному місці конфігурації, а не поширюються тут і там.
Огнян Димитров

89

Модуль IIS7 дозволить вам перенаправляти.

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

12
Також для IIS 7.0 вам потрібно встановити модуль перезапису Url 2.0
Chris

Я вважав це посилання простим і корисним у створенні будь-якої конкретної сторінки, щоб приймати лише https-запити - support.microsoft.com/kb/239875
Manik Arora

21

Для тих, хто використовує ASP.NET MVC. Ви можете використовувати наступне, щоб форсувати SSL / TLS через HTTPS на всьому сайті двома способами:

Важкий шлях

1 - Додайте RequireHttpsAttribute до глобальних фільтрів:

GlobalFilters.Filters.Add(new RequireHttpsAttribute());

2 - змусити маркери проти підробки використовувати SSL / TLS:

AntiForgeryConfig.RequireSsl = true;

3 - Потрібно, щоб файли cookie за замовчуванням вимагали HTTPS, змінивши файл Web.config:

<system.web>
    <httpCookies httpOnlyCookies="true" requireSSL="true" />
</system.web>

4 - Використовуйте пакет NWebSec.Owin NuGet і додайте наступний рядок коду, щоб дозволити сувору безпеку транспорту по всьому сайту. Не забудьте додати директиву попереднього завантаження нижче та подати свій сайт на сайт попереднього завантаження HSTS . Більше інформації тут і тут . Зауважте, що якщо ви не використовуєте OWIN, на веб- сайті NWebSec є метод Web.config, про який можна прочитати .

// app is your OWIN IAppBuilder app in Startup.cs
app.UseHsts(options => options.MaxAge(days: 30).Preload());

5 - Використовуйте пакет NWebSec.Owin NuGet та додайте наступний рядок коду, щоб увімкнути прив'язку відкритого ключа (HPKP) на сайті. Більше інформації тут і тут .

// app is your OWIN IAppBuilder app in Startup.cs
app.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: 30));

6 - Включіть схему https у будь-яку використану URL-адресу. HTTP-заголовок політики безпеки вмісту (CSP) та цілісність субресурсів (SRI) не грають добре, коли ви імітуєте схему в деяких браузерах. Краще бути явним щодо HTTPS. напр

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

Легкий шлях

Використовуйте шаблон проекту ASP.NET MVC Boilerplate Visual Studio, щоб створити проект із усім цим та багато іншого, який можна вбудувати. Ви також можете переглянути код на GitHub .


3
Також якщо ви користуєтесь <authentication mode="Forms">, всередині у вас повинен бути<forms requireSSL="true">
Плутон

1
@ muhammad-rehan-saeed Я використовую mvc5 котлован, але сайт не перенаправляє http на https автоматично на виробничий сервер, це робиться лише на localhost, чи щось мені не вистачає?
Дін

Це не правильний форум, щоб задавати це питання. Опублікуйте випуск на сайті GitHub. RequireHttpsAttributeРобить редирект. Поки у вас є, що це повинно бути добре.
Мухаммад Рехан Саїд

@MuhammadRehanSaeed, люблю свою відповідь. Але ... як мені отримати SHA256 хеш сертифіката, створеного за допомогою MakeCert? Все, що у мене є, - відбиток пальців SHA-1 ... Ви випадково знаєте?
Діана

1
@Diana це посилання може показати вам, як.
Мухаммад Рехан Саїд

13

Якщо ви не можете встановити це в IIS з будь-якої причини, я б створив модуль HTTP, який виконує переадресацію для вас:

using System;
using System.Web;

namespace HttpsOnly
{
    /// <summary>
    /// Redirects the Request to HTTPS if it comes in on an insecure channel.
    /// </summary>
    public class HttpsOnlyModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            // Note we cannot trust IsSecureConnection when 
            // in a webfarm, because usually only the load balancer 
            // will come in on a secure port the request will be then 
            // internally redirected to local machine on a specified port.

            // Move this to a config file, if your behind a farm, 
            // set this to the local port used internally.
            int specialPort = 443;

            if (!app.Context.Request.IsSecureConnection 
               || app.Context.Request.Url.Port != specialPort)
            {
               app.Context.Response.Redirect("https://" 
                  + app.Context.Request.ServerVariables["HTTP_HOST"] 
                  + app.Context.Request.RawUrl);    
            }
        }

        public void Dispose()
        {
            // Needed for IHttpModule
        }
    }
}

Потім просто компілюйте його в DLL, додайте його як посилання на ваш проект і розмістіть це в web.config:

 <httpModules>
      <add name="HttpsOnlyModule" type="HttpsOnly.HttpsOnlyModule, HttpsOnly" />
 </httpModules>

Це здається більш причетним, ніж просто наклеїти його на global.asax - просто цікаво, чи є перевага?
Брайан Маккей

1
Перевагою буде те, що ви не хочете ним користуватися, просто прокоментуйте модуль у своїй web.config. Це рішення можна налаштувати, тоді як інше - ні.
Bob Yexley

2
Я мало розгублений. Я очікував, що щось подібне app.BeginRequest += new OnBeginRequest;у Initметоді, а в OnBeginRequestби міститься те, що містить поточний Initметод. Ви впевнені, що цей модуль працює так, як очікувалося?
Якуб Штурч

Це не працює. Вам потрібно додати подію OnBeginRequest тощо, тоді вона працює.
SnAzBaZ

Я б відредагував цей несправний код, але для забезпечення його безпеки вам також знадобиться використовувати HSTS. Просто зайдіть з відповіддю Трої Хант і зробіть його модулем; див. support.microsoft.com/en-us/kb/307996 (старий, але добрий).
Марк Л.

4

Що вам потрібно зробити:

1) Додайте ключ всередину web.config, залежно від сервера виробництва або етапу, як показано нижче

<add key="HttpsServer" value="stage"/>
             or
<add key="HttpsServer" value="prod"/>

2) Всередині вашого файла Global.asax додайте метод нижче.

void Application_BeginRequest(Object sender, EventArgs e)
{
    //if (ConfigurationManager.AppSettings["HttpsServer"].ToString() == "prod")
    if (ConfigurationManager.AppSettings["HttpsServer"].ToString() == "stage")
    {
        if (!HttpContext.Current.Request.IsSecureConnection)
        {
            if (!Request.Url.GetLeftPart(UriPartial.Authority).Contains("www"))
            {
                HttpContext.Current.Response.Redirect(
                    Request.Url.GetLeftPart(UriPartial.Authority).Replace("http://", "https://www."), true);
            }
            else
            {
                HttpContext.Current.Response.Redirect(
                    Request.Url.GetLeftPart(UriPartial.Authority).Replace("http://", "https://"), true);
            }
        }
    }
}

3

Якщо підтримка SSL не налаштована на вашому сайті (тобто має бути можливість включити / вимкнути https) - ви можете використовувати атрибут [RequireHttps] для будь-яких дій контролера / контролера, які ви хочете захистити.



2

Для @Joe вище, "Це дає мені цикл переспрямування. Перш ніж я додав код, він спрацював нормально. Будь-які пропозиції? - Джо 8 листопада '11 о 4:13"

Це сталося і зі мною, і, на мою думку, трапляється те, що перед веб-сервером був балансир навантаження, який закінчував SSL-запит. Отже, мій веб-сайт завжди думав, що запит є "http", навіть якщо оригінальний браузер просив його бути "https".

Зізнаюсь, це трохи хакітно, але те, що для мене спрацювало, було реалізувати властивість "JustRedirected", яку я міг би використати, щоб з'ясувати, що людина вже була перенаправлена ​​один раз. Отже, я перевіряю конкретні умови, які вимагають переспрямування, і, якщо вони виконані, я встановлюю це властивість (значення, збережене в сеансі) перед перенаправленням. Навіть якщо умови перенаправлення http / https виконані вдруге, я обходжу логіку перенаправлення та скидаю значення сеансу "JustRedirected" на значення false. Вам знадобиться власна логіка тестування, але ось проста реалізація властивості:

    public bool JustRedirected
    {
        get
        {
            if (Session[RosadaConst.JUSTREDIRECTED] == null)
                return false;

            return (bool)Session[RosadaConst.JUSTREDIRECTED];
        }
        set
        {
            Session[RosadaConst.JUSTREDIRECTED] = value;
        }
    }

2

Я збираюся кинути свої два центи. Якщо у вас є доступ до сервера IIS, тоді ви можете змусити HTTPS використовувати протоколи прив'язки. Наприклад, у вас є веб-сайт під назвою Blah . У IIS ви встановите два сайти: Blah та Blah (Перенаправлення) . Для Blah налаштовуйте лише HTTPSприв'язку (і FTPякщо вам потрібно, переконайтесь, що також накладіть її на безпечне з'єднання). Для Blah (перенаправлення) налаштовуйте лише HTTPприв'язку. Нарешті, у розділі перенаправлення HTTP для Blah (перенаправлення) переконайтесь, що встановіть переспрямування 301 на Web.confighttps://blah.com , з точним пунктом призначення. Переконайтеся, що кожен сайт в IIS вказує на ньоговласна коренева папка, інакше все буде накручено. Також переконайтеся, що HSTSна вашому веб-сайті HTTPSed налаштовано так, щоб наступні запити браузера завжди змушені переносити HTTPS і не відбуватись переадресації.


2

Це більш повна відповідь на основі @Troy Hunt's. Додайте цю функцію до свого WebApplicationкласу в Global.asax.cs:

    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        // Allow https pages in debugging
        if (Request.IsLocal)
        {
            if (Request.Url.Scheme == "http")
            {
                int localSslPort = 44362; // Your local IIS port for HTTPS

                var path = "https://" + Request.Url.Host + ":" + localSslPort + Request.Url.PathAndQuery;

                Response.Status = "301 Moved Permanently";
                Response.AddHeader("Location", path);
            }
        }
        else
        {
            switch (Request.Url.Scheme)
            {
                case "https":
                    Response.AddHeader("Strict-Transport-Security", "max-age=31536000");
                    break;
                case "http":
                    var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
                    Response.Status = "301 Moved Permanently";
                    Response.AddHeader("Location", path);
                    break;
            }
        }
    }

(Щоб увімкнути SSL у вашій локальній збірці, увімкніть його в доці властивостей для проекту)


1

-> Просто додайте [RequireHttps] на вершині публічного класу HomeController: Controller.

-> І додати GlobalFilters.Filters.Add (новий RequireHttpsAttribute ()); у методі "захищеної недійсності Application_Start ()" у файлі Global.asax.cs.

Що змушує всю вашу програму до HTTPS.


Я не вірю, що це буде працювати на будь-яких сторінках, що використовуються за допомогою WebForms або будь-яких API, створених за допомогою WebAPI. Він буде охоплювати лише контролери MVC.
Марк Л.

1

Я колись шукав найкращих практик, які мають сенс, і знайшов наступне, що працювало для мене вдосконалено. Я сподіваюся, що це врятує вас колись.

Використання файлу Config (наприклад, веб-сайту asp.net) https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and- вище /

або на власному сервері https://www.sslshopper.com/iis7-redirect-http-to-https.html

[КОРОТКИЙ ВІДПОВІСТЬ] Просто Код, наведений нижче, знаходиться всередині

<system.webServer> 
 <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}{REQUEST_URI}" 
        redirectType="Permanent" />
        </rule>
       </rules>
 </rewrite>

1

В IIS10 (Windows 10 і Server 2016), починаючи з версії 1709, існує новий, простіший варіант включення HSTS для веб-сайту.

Microsoft описують переваги нового підходу тут , і надає безліч різних прикладів того , як здійснити зміну програмно або шляхом безпосереднього редагування файлу ApplicationHost.config (який , як web.config , але працює на IIS рівня, а не індивідуальний рівня сайту ). ApplicationHost.config можна знайти в C: \ Windows \ System32 \ inetsrv \ config.

Тут я окреслив два приклади методів, щоб уникнути гниття посилань.

Спосіб 1 - Відредагуйте файл ApplicationHost.config безпосередньо між <site>тегами, додайте цей рядок:

<hsts enabled="true" max-age="31536000" includeSubDomains="true" redirectHttpToHttps="true" />

Спосіб 2 - Командний рядок: Виконайте наступне з піднятого командного рядка (тобто правою мишкою на CMD та запустіть як адміністратор). Не забудьте поміняти Contoso на ім’я свого сайту, як це відображається в IIS Manager.

c:
cd C:\WINDOWS\system32\inetsrv\
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.enabled:True" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.max-age:31536000" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.includeSubDomains:True" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.redirectHttpToHttps:True" /commit:apphost

Інші методи, які Microsoft пропонує в цих статтях, можуть бути кращими варіантами, якщо ви перебуваєте в розміщеному середовищі, де у вас обмежений доступ.

Майте на увазі, що IIS10 версія 1709 зараз доступна в Windows 10, але для Windows Server 2016 вона знаходиться на іншій доріжці випуску, і не буде випущена як патч чи пакет оновлення. Тут див. Подробиці про 1709 рік.


0

Якщо ви використовуєте ASP.NET Core, ви можете спробувати нульовий пакет SaidOut.AspNetCore.HttpsWithStrictTransportSecurity.

Тоді вам потрібно лише додати

app.UseHttpsWithHsts(HttpsMode.AllowedRedirectForGet, configureRoutes: routeAction);

Це також додасть заголовок HTTP StrictTransportSecurity до всіх запитів, зроблених за схемою https.

Приклад коду та документації https://github.com/saidout/saidout-aspnetcore-httpswithstricttransportsecurity#example-code

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.