Кращий спосіб на 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.