Jak wymusić HTTPS przy użyciu pliku web.config

220

Szukałem w Google i StackOverflow, próbując znaleźć rozwiązanie tego problemu, ale wszystkie wydają się odnosić do ASP.NET itp.

Zwykle uruchamiam Linux na moich serwerach, ale dla tego jednego klienta korzystam z systemu Windows z IIS 7.5 (i Plesk 10). Z tego powodu jestem nieco obeznany z IIS i plikami web.config . W .htaccesspliku można użyć warunków ponownego zapisu, aby wykryć, czy protokołem jest HTTPS i odpowiednio przekierować. Czy istnieje prosty sposób na osiągnięcie tego celu za pomocą pliku web.config, a nawet za pomocą zainstalowanego modułu „ URL Rewrite ”?

Nie mam doświadczenia z ASP.NET, więc jeśli jest to zaangażowane w rozwiązanie, proszę podać jasne kroki wdrażania.

Powodem, dla którego robię to z web.config, a nie PHP, jest to, że chciałbym wymusić HTTPS na wszystkich zasobach w witrynie.

Ben Carey
źródło

Odpowiedzi:

427

Potrzebujesz modułu URL Rewrite, najlepiej v2 (nie mam zainstalowanego v1, więc nie mogę zagwarantować, że będzie tam działał, ale powinien).

Oto przykład takiego web.config - wymusi HTTPS dla WSZYSTKICH zasobów (przy użyciu stałego przekierowania 301):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="Redirect to https" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

PS To szczególne rozwiązanie nie ma nic wspólnego z ASP.NET/PHP ani żadną inną technologią, ponieważ jest wykonywane tylko przy użyciu modułu do przepisywania adresów URL - jest przetwarzane na jednym z początkowych / niższych poziomów - zanim żądanie dotrze do punktu, w którym kod zostaje stracony.

LazyOne
źródło
6
@BenCarey Powinieneś także spojrzeć na Strict-Transport-Securitynagłówek: en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
LazyOne
22
Zalecam zmianę przekierowania, aby nie dołączało ciągu zapytania, ponieważ jest on już częścią {REQUEST_URI} (w przeciwnym razie parametry zostaną dodane dwukrotnie). <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
franzo
6
Działa to, ale niestety także na localhost. Aby tego uniknąć, możesz dodać to do <warunków>: <add input = "{HTTP_HOST}" pattern = "localhost" negate = "true" />
wezzix
5
Używając elastycznej łodygi fasoli AWS, ta metoda dawała mi 302 Zbyt wiele przekierowań, dopóki nie zmodyfikowałem: <match url=".*"/>do<match url="http://*.*" />
Kevin R.
1
@Sam Może nie masz zainstalowanego modułu URL Rewrite? Domyślnie nie jest dostarczany z IIS, należy go zainstalować osobno. Np. Docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/…
LazyOne
80

Dla osób korzystających z ASP.NET MVC. Możesz użyć RequireHttpsAttribute, aby wymusić, aby wszystkie odpowiedzi były HTTPS:

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

Inne rzeczy, które możesz chcieć zrobić, aby zabezpieczyć swoją witrynę:

  1. Wymuś użycie tokenów zapobiegających fałszerstwom do korzystania z protokołu SSL / TLS:

    AntiForgeryConfig.RequireSsl = true;
  2. Wymagaj, aby pliki cookie wymagały domyślnie HTTPS poprzez zmianę pliku Web.config:

    <system.web>
        <httpCookies httpOnlyCookies="true" requireSSL="true" />
    </system.web>
    
  3. Użyj pakietu NWebSec.Owin NuGet i dodaj następujący wiersz kodu, aby włączyć Strict Transport Security (HSTS) w całej witrynie. Nie zapomnij dodać dyrektywy Preload poniżej i przesłać swoją stronę do strony HSTS Preload . Więcej informacji tutaj i tutaj . Pamiętaj, że jeśli nie używasz OWIN, istnieje metoda Web.config, którą możesz przeczytać na stronie NWebSec .

    // app is your OWIN IAppBuilder app in Startup.cs
    app.UseHsts(options => options.MaxAge(days: 720).Preload());
    
  4. Użyj pakietu NWebSec.Owin NuGet i dodaj następujący wiersz kodu, aby włączyć przypinanie klucza publicznego (HPKP) w całej witrynie. Więcej informacji tutaj i tutaj .

    // 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));
    
  5. Uwzględnij schemat https we wszystkich używanych adresach URL. Nagłówek HTTP Content Security Policy (CSP) i integralność podrzędnych zasobów (SRI) nie działają dobrze, jeśli naśladujesz schemat w niektórych przeglądarkach. Lepiej jest wyraźnie powiedzieć o HTTPS. na przykład

    <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/bootstrap.min.js">
    </script>
    
  6. Użyj szablonu projektu Visual Studio ASP.NET MVC Boilerplate, aby wygenerować projekt z tym wszystkim io wiele więcej wbudowanym. Możesz także wyświetlić kod w GitHub .

Muhammad Rehan Saeed
źródło
4
Pytanie dotyczy ASP.NET, ale nie zawiera formularzy WebForms ani MVC, więc udzieliłem wyczerpującej odpowiedzi dla tych, którzy używają MVC (który nie używa pliku Web.config do wymuszenia HTTPS), a jednak ... przegłosowali.
Muhammad Rehan Saeed
6
a) Rozwiązanie działa, ale wszystko się zmieniło, to ważne, wysoko ocenione pytanie zasługuje na zaktualizowaną odpowiedź przy użyciu tego, co jest wbudowane w MVC. b) Odpowiedź próbuje objąć wszystkie bazy. Pytanie nie jest proste, włączenie HTTPS w całej witrynie wymaga znacznie więcej niż zmiany pliku web.config. Czytelnicy mogą zostać wprowadzeni w błąd, myśląc, że wystarczy zmienić plik Web.config. Bezpieczeństwo jest wystarczająco trudne, ponieważ nie zawiera niepełnych / nieaktualnych odpowiedzi.
Muhammad Rehan Saeed,
11
Moim zdaniem jest to doskonała i cenna odpowiedź. Gdy ktoś przejdzie do tematu i zostanie skierowany na to pytanie, cieszę się, że Twoja odpowiedź jest tutaj.
Prezydent James K. Polk
1
@MuhammadRehanSaeed Nice post. Może dodać SRI do swojej listy? scotthelme.co.uk/subresource-integrity
Nathan
1
@MuhammadRehanSaeed true - Myślę, że nagłówek „Inne rzeczy, które możesz chcieć zrobić, aby zabezpieczyć swoją stronę”, przypomniał mi o tym :)
Nathan
14

Aby wzmocnić odpowiedź LazyOne, oto wersja odpowiedzi z adnotacją.

<rewrite>
  <rules>
     <clear />
     <rule name="Redirect all requests to https" stopProcessing="true">
       <match url="(.*)" />
         <conditions logicalGrouping="MatchAll">
           <add input="{HTTPS}" pattern="off" ignoreCase="true" />
         </conditions>
         <action 
            type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" 
            redirectType="Permanent" appendQueryString="false" />
     </rule>
  </rules>
</rewrite>

Wyczyść wszystkie pozostałe reguły, które mogły być już zdefiniowane na tym serwerze. Utwórz nową regułę, która nazwiemy „Przekieruj wszystkie żądania do https”. Po przetworzeniu tej reguły nie przetwarzaj więcej reguł! Dopasuj wszystkie przychodzące adresy URL. Następnie sprawdź, czy wszystkie pozostałe warunki są spełnione: HTTPS jest WYŁĄCZONY. To tylko jeden warunek (ale upewnij się, że to prawda). Jeśli tak, wyślij stałe przekierowanie 301 z powrotem do klienta na adres http://www.foobar.com/whatever?else=the#url-contains. Nie dodawaj ciągu zapytania na końcu, ponieważ spowoduje to skopiowanie ciągu zapytania!

To właśnie oznaczają właściwości, atrybuty i niektóre wartości.

  • wyczyść usuwa wszystkie reguły serwera, które w przeciwnym razie moglibyśmy odziedziczyć.
  • reguła definiuje regułę.
    • nazwij dowolną (choć unikalną) nazwę reguły.
    • stopPrzetwarzanie, czy natychmiast przekazać żądanie do potoku żądań IIS, czy najpierw przetworzyć dodatkowe reguły.
  • dopasuj, kiedy chcesz uruchomić tę regułę.
    • adres URL, na podstawie którego oceniany jest adres URL
  • warunki dodatkowe warunki dotyczące uruchomienia tej reguły; warunki są przetwarzane tylko wtedy, gdy występuje pierwsze dopasowanie.
    • logicalGrouping, czy wszystkie warunki muszą być prawdziwe ( MatchAll), czy którykolwiek z warunków musi być spełniony ( MatchAny); podobny do AND vs OR.
  • add dodaje warunek, który musi zostać spełniony.
    • wprowadź dane wejściowe, które ocenia warunek; dane wejściowe mogą być zmiennymi serwera.
    • wzorzec standard, na podstawie którego oceniać dane wejściowe.
    • ignoreCase, czy wielkie litery mają znaczenie, czy nie.
  • akcja , co zrobić, jeśli matchi jego conditionswszystkie są prawdziwe.
    • typ może być na ogół redirect(po stronie klienta) lub rewrite(po stronie serwera).
    • url, co wyprodukować w wyniku tej reguły; w takim przypadku należy połączyć https://dwie zmienne serwera.
    • redirectType jakiego przekierowania HTTP użyć; ten jest na stałe 301.
    • appendQueryString, czy dodać ciąg zapytania na końcu wynikowego, urlczy nie; w tym przypadku ustawiamy wartość false, ponieważ {REQUEST_URI}już zawiera.

Zmienne serwera to

  • {HTTPS}który jest albo OFFczy ON.
  • {HTTP_HOST}jest www.mysite.comi
  • {REQUEST_URI} zawiera resztę URI, np /home?key=value
    • przeglądarka obsługuje #fragment(patrz komentarz LazyOne).

Zobacz także: https://www.iis.net/learn/extensions/url-rewrite-module/url-rewrite-module-configuration-reference

Shaun Luttin
źródło
1
Jedna uwaga: fragmentaryczna część adresu URL (z /home?key=value#fragment) nie jest ustawiona na serwerze przez przeglądarki, ponieważ powinna być używana lokalnie.
LazyOne
@LazyOne Pytanie. Korzystamy z powyższego pliku web.config, aby przekierować z greenearth.game/about#foo do HTTPS. Przejście na HTTPS obejmuje fragment #foo. Biorąc pod uwagę, że część #foo nie jest wysyłana do serwera, w jaki sposób zawiera to przekierowanie?
Shaun Luttin
Jest obsługiwany przez przeglądarkę. Wystarczy otworzyć kartę sieciową w przeglądarce Google Chrome (lub podobnej w przeglądarce Firefox itp.) I zobaczyć, jaki adres URL jest faktycznie żądany (np. http://www.example.com/members#oopsŻądanie zostanie wysłane, na http://www.example.com/membersktóre następnie zostanie przekierowany do wersji HTTPS w https://www.example.com/members- przeglądarka
zajmie się
@LazyOne Dziękuję za to. Jeśli dobrze pamiętam, istnieje kilka błędów WebKit, które uniemożliwiają włączenie fragmentu do przekierowań. To ma sens. bugs.webkit.org/show_bug.cgi?id=24175
Shaun Luttin
1
en.wikipedia.org/wiki/Fragment_identifier - „Klienci nie powinni wysyłać fragmentów URI do serwerów podczas pobierania dokumentu i bez pomocy aplikacji lokalnej (patrz poniżej) fragmenty nie uczestniczą w przekierowaniach HTTP” - dla jasności, na wypadek, gdy źle zrozumiałem twój ostatni komentarz.
LazyOne
6

Przyjęta odpowiedź nie działała dla mnie. Postępowałem zgodnie z instrukcjami na tym blogu .

Kluczowym punktem, którego mi brakowało, było to, że musiałem pobrać i zainstalować narzędzie URL Rewrite dla IIS. Znalazłem to tutaj . Wynik był następujący.

<rewrite>
        <rules>
            <remove name="Http to Https" />
            <rule name="Http to Https" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
                <match url="*" />
                <conditions>
                    <add input="{HTTPS}" pattern="off" />
                </conditions>
                <serverVariables />
                <action type="Redirect" url="https://{HTTPS_HOST}{REQUEST_URI}" />
            </rule>
        </rules>
    </rewrite>
Eric
źródło
1

W .Net Core postępuj zgodnie z instrukcjami na https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl

W pliku startup.cs dodaj:

// Requires using Microsoft.AspNetCore.Mvc;
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MvcOptions>(options =>
    {
        options.Filters.Add(new RequireHttpsAttribute());
    });`enter code here`

Aby przekierować Http na Https, dodaj następujące w pliku startup.cs

// Requires using Microsoft.AspNetCore.Rewrite;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    var options = new RewriteOptions()
       .AddRedirectToHttps();

    app.UseRewriter(options);
Oszałamiający Człowiek
źródło
0

Doskonała biblioteka NWebsec może uaktualnić twoje żądania z HTTP do HTTPS za pomocą swojego upgrade-insecure-requestsznacznika w Web.config:

<nwebsec>
  <httpHeaderSecurityModule>
    <securityHttpHeaders>
      <content-Security-Policy enabled="true">
        <upgrade-insecure-requests enabled="true"  />
      </content-Security-Policy>
    </securityHttpHeaders>
  </httpHeaderSecurityModule>
</nwebsec>
Co on robi
źródło
0

Nie mogłem instalować przepisywania adresów URL w moim środowisku, więc znalazłem inną ścieżkę.

Dodając to do mojego pliku web.config, dodałem błąd przepisywania i działałem na IIS 7.5:

<system.webServer>
    <httpErrors errorMode="Custom" defaultResponseMode="File" defaultPath="C:\WebSites\yoursite\" >    
    <remove statusCode="403" subStatusCode="4" />
    <error statusCode="403" subStatusCode="4" responseMode="File" path="redirectToHttps.html" />
</httpErrors>

Następnie postępując zgodnie z radą tutaj: https://www.sslshopper.com/iis7-redirect-http-to-https.html

Utworzyłem plik HTML, który przekierowuje (redirectToHttps.html):

<html>
<head><title>Redirecting...</title></head>
<script language="JavaScript">
function redirectHttpToHttps()
{
    var httpURL= window.location.hostname + window.location.pathname + window.location.search;
    var httpsURL= "https://" + httpURL;
    window.location = httpsURL;
}
redirectHttpToHttps();
</script>
<body>
</body>
</html>

Mam nadzieję, że ktoś uzna to za przydatne, ponieważ nie mogłem znaleźć wszystkich elementów w jednym miejscu nigdzie indziej.

Spencer Sullivan
źródło
-7

Prostym sposobem jest powiedzieć IIS wysłać swój własny plik błędu HTTP żądań. Plik może następnie zawierać przekierowanie meta, przekierowanie JavaScript i instrukcje z łączem itp. Co ważne, nadal możesz zaznaczyć opcję „Wymagaj SSL” dla witryny (lub folderu), a to zadziała.

</configuration>
</system.webServer>
    <httpErrors>
        <clear/>
        <!--redirect if connected without SSL-->
        <error statusCode="403" subStatusCode="4" path="errors\403.4_requiressl.html" responseMode="File"/>
    </httpErrors>
</system.webServer>
</configuration>
przeadresować
źródło
Dlaczego głosowanie negatywne? Działa i odpowiada na pytanie.
przekierowanie
14
To jest głos negatywny, ponieważ mówisz Google, że nie znaleziono pliku, a następnie używasz JavaScript do przekierowania, co zwykle jest po prostu złe.
Thomas Bennett,