Der beste Weg in asp.net, https für eine ganze Site zu erzwingen?

192

Vor ungefähr 6 Monaten habe ich eine Site eingeführt, auf der jede Anfrage über https erfolgen musste. Die einzige Möglichkeit, um sicherzustellen, dass jede Anforderung an eine Seite über https erfolgte, bestand darin, sie beim Laden der Seite zu überprüfen. Wenn die Anfrage nicht über http wäre, würde ich response.redirect (" https://example.com ")

Gibt es einen besseren Weg - idealerweise eine Einstellung in der web.config?

Codethrift
quelle
Überprüfen Sie meine Antwort hier stackoverflow.com/questions/33882350/…
Shady Sherif

Antworten:

250

Bitte verwenden Sie HSTS (HTTP Strict Transport Security)

von 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>

Ursprüngliche Antwort (ersetzt durch die oben genannte am 4. Dezember 2015)

Grundsätzlich

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

das würde in der global.asax.cs (oder global.asax.vb) gehen

Ich kenne keine Möglichkeit, es in der web.config anzugeben

John Boker
quelle
7
Das funktioniert, war aber gefährlich für mich: Als ich versuchte, mit diesem Code lokal in VS 2010 auszuführen, wurde meine Startseite nie geladen. Stattdessen habe ich gerade die Meldung "Diese Webseite ist nicht verfügbar" erhalten. Um dies zu beheben, habe ich eine zweite Bedingung hinzugefügt, um zu testen, ob die URL die Zeichenfolge "localhost" enthält: Wenn dies nicht der Fall ist, wird https erzwungen.
mg1075
3
Dies gibt mir eine Umleitungsschleife. Bevor ich den Code hinzugefügt habe, hat es gut funktioniert. Irgendwelche Vorschläge?
Joe
9
Bitte beachten Sie, dass dies keinerlei nützliche Sicherheit bietet. Tatsächlich werden nur Verbindungen von Benutzern gesichert, die bereits sicher sind, und diejenigen, die angegriffen werden, können nicht gesichert werden (dies liegt daran, dass ein MITM die Umleitung einfach ganz weglassen und alles an Ihre "sichere" Site weiterleiten kann). Meiner Meinung nach ist das Umleiten von Benutzeragenten nur eine Wohlfühl-Voodoo-Sicherheit und bietet eine manchmal gefährliche Illusion von Sicherheit. Der einzige Weg besteht darin, die Benutzeragenten anzuweisen, nur sichere Ressourcen anzufordern und sie nicht umzuleiten, wenn dies nicht der Fall ist. Dies ist, was HSTS tut - siehe Antworten unten.
Der
2
Diese Antwort sollte als "schädlich" angesehen und nicht verwendet werden. Laut Kommentar von @tne oben.
Rosdi Kasim
2
@RosdiKasim Sollte diese Antwort seit der Bearbeitung am 4. Dezember 15 immer noch als schädlich angesehen werden?
Andrew Morton
123

Sie können auch HSTS verwenden, indem Sie den Header "Strict-Transport-Security" an den Browser zurückgeben. Der Browser muss dies unterstützen (und derzeit sind es hauptsächlich Chrome und Firefox). Dies bedeutet jedoch, dass der Browser nach dem Festlegen keine Anforderungen an die Site über HTTP stellt und diese stattdessen in HTTPS-Anforderungen übersetzt, bevor sie ausgegeben werden . Versuchen Sie dies in Kombination mit einer Weiterleitung von 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;
  }
}

Browser, die HSTS nicht kennen, ignorieren den Header einfach, werden jedoch von der switch-Anweisung abgefangen und an HTTPS gesendet.

Troy Hunt
quelle
6
Ich habe noch nie von dem HSTS-Header gehört, sehe aber ziemlich cool aus. Gibt es einen Grund, einen so kleinen Maximalalterwert (5 Minuten) zu verwenden? Der Wikipedia-Artikel, auf den Sie verlinken, schlägt vor, einen großen Wert (6-12 Monate) festzulegen.
Dana
5
+1. Lesen Sie diesen sehr umfangreichen Artikel in Troys Blog, der Details darüber enthält, warum nur die Verwendung von Weiterleitungen die Sicherheit verringern kann. Hinweis: Dadurch können Sie unter anderem für das SSL-Strip-Tool anfällig werden. troyhunt.com/2011/11/…
Oran Dennison
3
Es lohnt sich auch, NWebsec zu besuchen , was dies (und mehr) sehr einfach macht.
Tieson T.
16
Sie sollten den Switch einwickeln, if(!Request.IsLocal)damit das Debuggen nicht unterbrochen wird.
Justin J Stark
1
Gute Antwort. Eine Subtilität - Für die HTTP-Header ("Strict-Transport-Security") ist es besser, eine Bibliothek wie NWebSec zu verwenden, da es mehrere Optionen gibt, die sich auf einen Konfigurationsort konzentrieren, anstatt sich hier und da auszubreiten.
Ognyan Dimitrov
89

Mit dem IIS7-Modul können Sie umleiten.

    <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>
Kennzeichen
quelle
12
Außerdem müssen Sie für IIS 7.0 das Url Rewrite Module 2.0
Chris
Ich fand diesen Link einfach und hilfreich, damit eine bestimmte Seite nur https-Anfragen akzeptiert - support.microsoft.com/kb/239875
Manik Arora
21

Für Benutzer von ASP.NET MVC. Sie können Folgendes verwenden, um SSL / TLS über HTTPS auf zwei Arten auf der gesamten Site zu erzwingen:

Der harte Weg

1 - Fügen Sie den globalen Filtern das RequireHttpsAttribute hinzu:

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

2 - Anti-Fälschungs-Token zur Verwendung von SSL / TLS zwingen:

AntiForgeryConfig.RequireSsl = true;

3 - Cookies müssen standardmäßig HTTPS erfordern, indem Sie die Datei Web.config ändern:

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

4 - Verwenden Sie das NWebSec.Owin NuGet-Paket und fügen Sie die folgende Codezeile hinzu, um die strikte Transportsicherheit auf der gesamten Site zu aktivieren. Vergessen Sie nicht, die unten stehende Preload-Direktive hinzuzufügen und Ihre Site an die HSTS Preload-Site zu senden . Weitere Informationen hier und hier . Beachten Sie, dass es eine Web.config-Methode gibt, die Sie auf der NWebSec- Site nachlesen können, wenn Sie OWIN nicht verwenden .

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

5 - Verwenden Sie das NWebSec.Owin NuGet-Paket und fügen Sie die folgende Codezeile hinzu, um das Festhalten öffentlicher Schlüssel (Public Key Pinning, HPKP) auf der gesamten Site zu aktivieren. Weitere Informationen hier und hier .

// 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 - Fügen Sie das https-Schema in die verwendeten URLs ein. Der HTTP-Header für Content Security Policy (CSP) und die Subresource Integrity (SRI) funktionieren nicht gut, wenn Sie das Schema in einigen Browsern imitieren. Es ist besser, explizit über HTTPS zu sprechen. z.B

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

Der einfache Weg

Verwenden Sie die Visual Studio-Projektvorlage von ASP.NET MVC Boilerplate , um ein Projekt mit all dem und vielem mehr zu generieren. Sie können den Code auch auf GitHub anzeigen .

Muhammad Rehan Saeed
quelle
3
Auch wenn Sie verwenden <authentication mode="Forms">, müssen Sie drinnen haben<forms requireSSL="true">
Pluto
1
@ muhammad-rehan-saeed Ich verwende mvc5 boilerplate, aber die Site leitet http auf dem Produktionsserver nicht automatisch zu https um. Dies geschieht nur auf localhost. Fehlt mir etwas?
Diin
Dies ist nicht das richtige Forum, um diese Frage zu stellen. Veröffentlichen Sie ein Problem auf der GitHub-Website. Das RequireHttpsAttributemacht die Weiterleitung. Solange du das hast, sollte es in Ordnung sein.
Muhammad Rehan Saeed
@ MuhammadRehanSaeed, liebe deine Antwort. Aber ... wie bekomme ich den SHA256-Hash eines mit MakeCert erstellten Zertifikats? Ich habe nur einen SHA-1-Fingerabdruck ... Weißt du es zufällig?
Diana
1
@ Diana dieser Link kann dir zeigen wie.
Muhammad Rehan Saeed
13

Wenn Sie dies aus irgendeinem Grund nicht in IIS einrichten können, würde ich ein HTTP-Modul erstellen, das die Umleitung für Sie übernimmt:

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

Kompilieren Sie es dann einfach zu einer DLL, fügen Sie es als Referenz zu Ihrem Projekt hinzu und platzieren Sie es in web.config:

 <httpModules>
      <add name="HttpsOnlyModule" type="HttpsOnly.HttpsOnlyModule, HttpsOnly" />
 </httpModules>
FlySwat
quelle
Dies scheint mehr zu tun zu haben, als es nur in die global.asax zu stecken - nur neugierig, gibt es einen Vorteil?
Brian MacKay
1
Der Vorteil wäre, wenn Sie es nicht verwenden möchten, kommentieren Sie einfach das Modul in Ihrer web.config aus. Diese Lösung ist konfigurierbar, die andere nicht.
Bob Yexley
2
Ich bin wenig verwirrt. Ich hatte so etwas wie app.BeginRequest += new OnBeginRequest;in der InitMethode erwartet und in der OnBeginRequestwürde enthalten, was die aktuelle InitMethode enthält. Sind Sie sicher, dass dieses Modul wie erwartet funktioniert?
Jakub Šturc
Es funktioniert nicht. Sie müssen das OnBeginRequest-Ereignis usw. hinzufügen, dann funktioniert es.
SnAzBaZ
Ich würde diesen fehlerhaften Code bearbeiten, aber um ihn sicher zu machen, müssten Sie auch HSTS verwenden. Gehen Sie einfach mit Troy Hunts Antwort und machen Sie es zu einem Modul. Siehe support.microsoft.com/en-us/kb/307996 (ein Oldie, aber ein Goodie).
Marc L.
4

Was Sie tun müssen, ist:

1) Fügen Sie einen Schlüssel in web.config hinzu, abhängig von der Produktion oder dem Stage Server wie unten

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

2) Fügen Sie in Ihrer Global.asax-Datei die folgende Methode hinzu.

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);
            }
        }
    }
}
Chandan Kumar
quelle
3

Wenn die SSL-Unterstützung auf Ihrer Site nicht konfigurierbar ist (dh https ein- und ausgeschaltet werden sollte), können Sie das Attribut [RequireHttps] für jede Controller- / Controller-Aktion verwenden, die Sie sichern möchten.

Yarg
quelle
2

X-WebMux-SSL-termination: trueDies hängt auch von der Marke Ihres Balancers ab. Für den Web-Mux müssten Sie nach dem http-Header suchen, um festzustellen, ob der eingehende Datenverkehr ssl war. Details hier: http://www.cainetworks.com/support/redirect2ssl.html

Alexander
quelle
2

Für @Joe oben: "Dies gibt mir eine Umleitungsschleife. Bevor ich den Code hinzugefügt habe, hat es gut funktioniert. Irgendwelche Vorschläge? - Joe 8. November 11 um 4:13"

Dies passierte auch mir und ich glaube, dass ein Load Balancer die SSL-Anforderung vor dem Webserver beendete. Meine Website dachte also immer, die Anfrage sei "http", auch wenn der ursprüngliche Browser "https" angefordert hatte.

Ich gebe zu, dass dies ein bisschen hackig ist, aber was für mich funktioniert hat, war die Implementierung einer "JustRedirected" -Eigenschaft, die ich nutzen konnte, um herauszufinden, dass die Person bereits einmal umgeleitet wurde. Daher teste ich auf bestimmte Bedingungen, die die Umleitung rechtfertigen, und setze diese Eigenschaft (in der Sitzung gespeicherter Wert) vor der Umleitung, wenn sie erfüllt sind. Selbst wenn die http / https-Bedingungen für die Umleitung beim zweiten Mal erfüllt sind, umgehe ich die Umleitungslogik und setze den Sitzungswert "JustRedirected" auf false zurück. Sie benötigen Ihre eigene bedingte Testlogik, aber hier ist eine einfache Implementierung der Eigenschaft:

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

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

Ich werde meine zwei Cent einwerfen. Wenn Sie Zugriff auf die IIS-Serverseite haben, können Sie HTTPS mithilfe der Protokollbindungen erzwingen. Zum Beispiel haben Sie eine Website namens Blah . In IIS würden Sie zwei Sites einrichten : Blah und Blah (Redirect) . Konfigurieren Sie für Blah nur die HTTPSBindung (und stellen FTPSie bei Bedarf sicher, dass diese auch über eine sichere Verbindung erzwungen wird). Konfigurieren Sie für Blah (Redirect) nur die HTTPBindung. Stellen Sie schließlich im Abschnitt HTTP-Umleitung für Blah (Umleitung) sicher, dass eine 301-Umleitung https://blah.commit aktiviertem genauem Ziel festgelegt ist. Stellen Sie sicher, dass jede Site in IIS darauf verweisteigenen Stammordner, sonst wird die Web.config alles vermasselt. HSTSStellen Sie außerdem sicher, dass Sie auf Ihrer HTTPSed-Site eine Konfiguration vorgenommen haben, damit nachfolgende Anforderungen des Browsers immer an HTTPS erzwungen werden und keine Weiterleitungen auftreten.

Gup3rSuR4c
quelle
2

Dies ist eine umfassendere Antwort, die auf @Troy Hunts basiert. Fügen Sie diese Funktion Ihrer WebApplicationKlasse hinzu in 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;
            }
        }
    }

(Um SSL in Ihrem lokalen Build zu aktivieren, aktivieren Sie es im Eigenschaften-Dock für das Projekt.)

Noelicus
quelle
1

-> Fügen Sie einfach [RequireHttps] über dem öffentlichen HomeController: Controller hinzu.

-> Und fügen Sie GlobalFilters.Filters.Add hinzu (neues RequireHttpsAttribute ()); in der Methode 'protected void Application_Start ()' in der Datei Global.asax.cs.

Dadurch wird Ihre gesamte Anwendung auf HTTPS gezwungen.

Santosh K.
quelle
Ich glaube nicht, dass dies für Seiten funktioniert, die mit WebForms oder mit WebAPI erstellten APIs bereitgestellt werden. Es werden nur MVC-Controller behandelt.
Marc L.
1

Ich habe einige Zeit nach sinnvollen Best Practices gesucht und Folgendes gefunden, das für mich perfekt funktioniert hat. Ich hoffe das wird dich irgendwann retten.

Verwenden der Konfigurationsdatei (z. B. einer asp.net-Website) https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and- höher/

oder auf Ihrem eigenen Server https://www.sslshopper.com/iis7-redirect-http-to-https.html

[KURZE ANTWORT] Einfach Der folgende Code geht hinein

<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>
Nour Lababidi
quelle
1

In IIS10 (Windows 10 und Server 2016) gibt es ab Version 1709 eine neue, einfachere Option zum Aktivieren von HSTS für eine Website.

Microsoft beschreibt die Vorteile des neuen Ansatzes hier und bieten viele verschiedene Beispiele dafür , wie die Änderung programmatisch zu implementieren oder direkt die ApplicationHost.config - Datei bearbeiten (die wie web.config ist aber arbeitet auf der Ebene IIS, anstatt einzelne Site - Ebene ). ApplicationHost.config befindet sich unter C: \ Windows \ System32 \ inetsrv \ config.

Ich habe hier zwei der Beispielmethoden beschrieben, um Link Rot zu vermeiden.

Methode 1 - Bearbeiten Sie die Datei ApplicationHost.config direkt. <site>Fügen Sie zwischen den Tags die folgende Zeile hinzu:

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

Methode 2 - Befehlszeile: Führen Sie Folgendes an einer Eingabeaufforderung mit erhöhten Rechten aus (dh mit der rechten Maustaste auf CMD und als Administrator ausführen). Denken Sie daran, Contoso mit dem Namen Ihrer Site zu tauschen, wie er im IIS-Manager angezeigt wird.

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

Die anderen Methoden, die Microsoft in diesen Artikeln anbietet, sind möglicherweise bessere Optionen, wenn Sie sich in einer gehosteten Umgebung befinden, in der Sie nur eingeschränkten Zugriff haben.

Beachten Sie, dass IIS10 Version 1709 jetzt unter Windows 10 verfügbar ist. Für Windows Server 2016 befindet es sich jedoch auf einem anderen Release-Track und wird nicht als Patch oder Service Pack veröffentlicht. Siehe hier für Details über 1709.

Mike
quelle
0

Wenn Sie ASP.NET Core verwenden, können Sie das Nuget-Paket SaidOut.AspNetCore.HttpsWithStrictTransportSecurity ausprobieren.

Dann müssen Sie nur noch hinzufügen

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

Dadurch wird auch der HTTP-StrictTransportSecurity-Header zu allen Anforderungen hinzugefügt, die mithilfe des https-Schemas gestellt werden.

Beispielcode und Dokumentation https://github.com/saidout/saidout-aspnetcore-httpswithstricttransportsecurity#example-code

user7755300
quelle