Cara terbaik di asp.net untuk memaksa https untuk seluruh situs?

192

Sekitar 6 bulan yang lalu saya meluncurkan situs di mana setiap permintaan harus lebih dari https. Satu-satunya cara pada saat itu saya dapat menemukan untuk memastikan bahwa setiap permintaan ke halaman lebih dari https adalah dengan memeriksanya di acara memuat halaman. Jika permintaan tidak melebihi http, saya akan response.redirect (" https://example.com ")

Apakah ada cara yang lebih baik - idealnya beberapa pengaturan di web.config?

codethrift
sumber
periksa jawaban saya di sini stackoverflow.com/questions/33882350/…
Shady Sherif

Jawaban:

250

Silakan gunakan HSTS (HTTP Strict Transport Security)

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

Jawaban Asli (diganti dengan yang di atas pada 4 Desember 2015)

pada dasarnya

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

yang akan masuk dalam global.asax.cs (atau global.asax.vb)

saya tidak tahu cara untuk menentukannya di web.config

John Boker
sumber
7
Ini berfungsi, tetapi itu berbahaya bagi saya: ketika saya mencoba untuk menjalankan secara lokal di VS 2010 dengan kode ini berjalan, halaman awal saya tidak pernah dimuat; alih-alih, saya baru saja menerima pesan "Halaman web ini tidak tersedia". Untuk memperbaikinya, saya menambahkan kondisi kedua untuk menguji apakah url berisi string "localhost": jika tidak, maka paksa https.
mg1075
3
Ini memberi saya loop pengalihan. Sebelum saya menambahkan kode itu berfungsi dengan baik. Ada saran?
Joe
9
Harap dicatat bahwa ini tidak memberikan keamanan apa pun yang berguna. Sebenarnya, itu hanya akan mengamankan koneksi dari pengguna yang sudah aman, dan akan gagal untuk mengamankan mereka yang sedang diserang (ini karena MITM dapat dengan mudah menghilangkan pengalihan sama sekali dan meneruskan semuanya ke situs "aman" Anda). IMHO, mengarahkan ulang agen pengguna hanyalah keamanan voodoo yang baik, dan memberikan ilusi keselamatan yang terkadang berbahaya. Satu-satunya cara untuk pergi adalah menginstruksikan agen pengguna untuk hanya meminta sumber daya yang aman, bukan mengarahkan mereka jika mereka tidak. Inilah yang dilakukan HSTS - lihat jawaban di bawah.
mentega
2
Jawaban ini harus dianggap 'berbahaya' dan tidak boleh digunakan. Sesuai komentar oleh @tne di atas.
Rosdi Kasim
2
@RosdiKasim Haruskah jawaban ini dianggap berbahaya sejak suntingan 4 Des '15?
Andrew Morton
123

Hal lain yang dapat Anda lakukan adalah menggunakan HSTS dengan mengembalikan header "Strict-Transport-Security" ke browser. Peramban harus mendukung ini (dan saat ini, terutama Chrome dan Firefox yang mendukung), tetapi itu berarti bahwa setelah ditetapkan, peramban tidak akan membuat permintaan ke situs melalui HTTP dan sebaliknya akan menerjemahkannya ke permintaan HTTPS sebelum mengeluarkannya . Coba ini dalam kombinasi dengan pengalihan dari 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 yang tidak mengetahui HSTS hanya akan mengabaikan header tetapi masih akan tertangkap oleh pernyataan beralih dan dikirim ke HTTPS.

Troy Hunt
sumber
6
Belum pernah mendengar tentang tajuk HSTS sebelumnya, tetapi terlihat cukup keren. Apakah ada alasan untuk menggunakan nilai usia maks kecil (5 menit)? Artikel Wikipedia yang Anda tautkan menyarankan pengaturan ke nilai yang besar (6-12 bulan).
dana
5
+1. lihat artikel yang sangat luas ini di blog Troy yang mencakup perincian mengapa hanya menggunakan pengalihan dapat mengurangi keamanan. Petunjuk: itu dapat membuat Anda rentan terhadap alat Strip SSL, antara lain. troyhunt.com/2011/11/11 ...
Oran Dennison
3
Juga patut untuk dicoba NWebsec , yang membuat ini (dan banyak lagi) sangat mudah.
Tieson T.
16
Anda akan ingin membungkus switch if(!Request.IsLocal)agar tidak merusak debugging.
Justin J Stark
1
Jawaban yang bagus. Satu kehalusan - Untuk header Http ("Strict-Transport-Security") lebih baik menggunakan pustaka seperti NWebSec karena ada beberapa opsi yang terkonsentrasi di satu tempat konfigurasi daripada menyebar di sana-sini.
Ognyan Dimitrov
89

Modul IIS7 akan memungkinkan Anda mengarahkan ulang.

    <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>
Menandai
sumber
12
Juga, untuk IIS 7.0, Anda perlu menginstal Url Rewrite Module 2.0
Chris
Saya menemukan tautan ini sederhana dan bermanfaat dalam membuat halaman tertentu untuk hanya menerima permintaan https - support.microsoft.com/kb/239875
Manik Arora
21

Bagi yang menggunakan ASP.NET MVC. Anda dapat menggunakan yang berikut untuk memaksa SSL / TLS melalui HTTPS di seluruh situs dengan dua cara:

Jalan yang Keras

1 - Tambahkan RequireHttpsAttribute ke filter global:

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

2 - Paksa token Anti-Pemalsuan untuk menggunakan SSL / TLS:

AntiForgeryConfig.RequireSsl = true;

3 - Membutuhkan Cookie untuk meminta HTTPS secara default dengan mengubah file Web.config:

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

4 - Gunakan paket NWebSec.Owin NuGet dan tambahkan baris kode berikut untuk mengaktifkan Keamanan Transportasi Ketat di seluruh situs. Jangan lupa untuk menambahkan arahan Preload di bawah ini dan kirimkan situs Anda ke situs Preload HSTS . Informasi lebih lanjut di sini dan di sini . Perhatikan bahwa jika Anda tidak menggunakan OWIN, ada metode Web.config yang dapat Anda baca di situs NWebSec .

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

5 - Gunakan paket NWebSec.Owin NuGet dan tambahkan baris kode berikut untuk mengaktifkan Pinning Kunci Publik (HPKP) di seluruh situs. Informasi lebih lanjut di sini dan di sini .

// 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 - Sertakan skema https dalam URL apa pun yang digunakan. Kebijakan Keamanan Konten (CSP) HTTP header dan Subresource Integrity (SRI) tidak bermain bagus ketika Anda meniru skema di beberapa browser. Lebih baik untuk eksplisit tentang HTTPS. misalnya

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

Cara Mudah

Gunakan template proyek ASP.NET MVC Boilerplate Visual Studio untuk menghasilkan sebuah proyek dengan semua ini dan lebih banyak lagi bawaannya. Anda juga dapat melihat kode pada GitHub .

Muhammad Rehan Saeed
sumber
3
Juga jika menggunakan <authentication mode="Forms">, di dalam Anda harus memiliki<forms requireSSL="true">
Pluto
1
@ muhammad-rehan-saeed Saya menggunakan boilerplate mvc5 tetapi situs ini tidak mengarahkan http ke https secara otomatis pada server produksi yang melakukannya hanya di localhost apakah ada sesuatu yang saya lewatkan?
Diin
Ini bukan forum yang tepat untuk menanyakan pertanyaan ini. Posting masalah di situs GitHub. Apakah RequireHttpsAttributemelakukan redirect. Selama Anda memilikinya harus baik-baik saja.
Muhammad Rehan Saeed
@MuhammadRehanSaeed, cintai jawaban Anda. Tapi ... bagaimana saya mendapatkan hash SHA256 dari sertifikat yang dibuat dengan MakeCert? Yang saya miliki adalah sidik jari SHA-1 ... Apakah Anda kebetulan tahu?
Diana
1
@Diana tautan ini dapat menunjukkan caranya.
Muhammad Rehan Saeed
13

Jika Anda tidak dapat mengatur ini di IIS untuk alasan apa pun, saya akan membuat modul HTTP yang melakukan pengalihan untuk Anda:

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

Kemudian cukup kompilasi ke DLL, tambahkan sebagai referensi ke proyek Anda dan letakkan ini di web.config:

 <httpModules>
      <add name="HttpsOnlyModule" type="HttpsOnly.HttpsOnlyModule, HttpsOnly" />
 </httpModules>
FlySwat
sumber
Ini tampaknya lebih terlibat daripada hanya menempel di global.asax - hanya ingin tahu, apakah ada keuntungan?
Brian MacKay
1
Keuntungannya adalah, ketika Anda tidak ingin menggunakannya, cukup beri komentar modul di web.config Anda. Solusi ini dapat dikonfigurasi, sedangkan yang lainnya tidak.
Bob Yexley
2
Saya sedikit bingung. Saya mengharapkan sesuatu seperti app.BeginRequest += new OnBeginRequest;di dalam Initmetode dan di OnBeginRequestakan berisi apa Inityang berisi metode saat ini. Apakah Anda yakin modul ini berfungsi seperti yang diharapkan?
Jakub Šturc
Tidak bekerja. Anda perlu menambahkan event OnBeginRequest dll, lalu berfungsi.
SnAzBaZ
Saya akan mengedit kode yang salah ini, tetapi untuk membuatnya aman, Anda juga harus menggunakan HSTS. Pergilah dengan jawaban Troy Hunt dan jadikan modul; lihat support.microsoft.com/en-us/kb/307996 (oldie, tapi goodie).
Marc L.
4

Yang perlu Anda lakukan adalah:

1) Tambahkan kunci di dalam web.config, tergantung pada server produksi atau tahap seperti di bawah ini

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

2) Di dalam file Global.asax Anda tambahkan metode di bawah ini.

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
sumber
3

Jika dukungan SSL tidak dapat dikonfigurasi di situs Anda (mis. Harus dapat mengaktifkan / menonaktifkan https) - Anda dapat menggunakan atribut [RequireHttps] pada tindakan pengontrol / pengontrol yang ingin Anda amankan.

Yarg
sumber
2

Ini juga tergantung pada merek penyeimbang Anda, untuk mux web, Anda harus mencari header http X-WebMux-SSL-termination: trueuntuk mengetahui bahwa lalu lintas masuk adalah ssl. detail di sini: http://www.cainetworks.com/support/redirect2ssl.html

Alexander
sumber
2

Untuk @ Jo di atas, "Ini memberi saya loop redirect. Sebelum saya menambahkan kode itu berfungsi dengan baik. Ada saran? - Joe 8 '11 pada 4:13"

Ini juga terjadi pada saya dan yang saya yakini sedang terjadi adalah ada penyeimbang beban yang menghentikan permintaan SSL di depan server Web. Jadi, situs web saya selalu berpikir permintaan itu "http", bahkan jika browser asli memintanya "https".

Saya akui ini agak bangkrut, tetapi yang berhasil bagi saya adalah menerapkan properti "JustRedirected" yang dapat saya manfaatkan untuk mengetahui bahwa orang tersebut sudah dialihkan sekali. Jadi, saya menguji untuk kondisi tertentu yang menjamin pengalihan dan, jika dipenuhi, saya mengatur properti ini (nilai disimpan dalam sesi) sebelum pengalihan. Bahkan jika kondisi http / https untuk redirection terpenuhi untuk kedua kalinya, saya memotong logika redirection dan mereset nilai sesi "JustRedirected" menjadi false. Anda akan memerlukan logika pengujian bersyarat Anda sendiri, tetapi berikut ini adalah implementasi sederhana dari properti:

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

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

Saya akan memasukkan dua sen saya. JIKA Anda memiliki akses ke sisi server IIS, maka Anda dapat memaksa HTTPS dengan menggunakan binding protokol. Misalnya, Anda memiliki situs web yang disebut Blah . Di IIS Anda akan menyiapkan dua situs: Blah , dan Blah (Redirect) . Untuk Blah hanya mengkonfigurasi HTTPSpenjilidan (dan FTPjika Anda perlu, pastikan untuk memaksanya melalui koneksi yang aman juga). Untuk Blah (Redirect) hanya konfigurasikan HTTPbinding. Terakhir, di bagian HTTP Redirect untuk folder root Blah (Redirect) pastikan untuk mengatur 301 redirect ke , dengan tujuan yang tepat diaktifkan. Pastikan setiap situs di IIS menunjukkannyasendiri jika tidak maka semua akan kacau. Pastikan juga memilikinyahttps://blah.com Web.configHSTS dikonfigurasi pada situs HTTPS Anda sehingga permintaan berikutnya oleh browser selalu dipaksa ke HTTPS dan tidak ada pengalihan yang terjadi.

Gup3rSuR4c
sumber
2

Ini adalah jawaban yang lebih lengkap berdasarkan @Troy Hunt's. Tambahkan fungsi ini ke WebApplicationkelas Anda di 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;
            }
        }
    }

(Untuk mengaktifkan SSL pada bangunan lokal Anda, aktifkan di Properties dock untuk proyek)

Noelicus
sumber
1

-> Cukup ADD [RequireHttps] di atas kelas publik HomeController: Controller.

-> Dan tambahkan GlobalFilters.Filters.Add (RequireHttpsAttribute ()) baru; dalam metode 'protected void Application_Start ()' dalam file Global.asax.cs.

Yang memaksa seluruh aplikasi Anda ke HTTPS.

Santosh K
sumber
Saya tidak percaya ini akan berfungsi untuk halaman apa pun yang disajikan menggunakan WebForms atau API apa pun yang dibangun dengan WebAPI. Ini hanya akan mencakup pengontrol MVC.
Marc L.
1

Saya menghabiskan beberapa waktu mencari praktik terbaik yang masuk akal dan menemukan yang berikut ini berfungsi dengan baik untuk saya. Saya berharap ini akan menyelamatkan Anda kapan-kapan.

Menggunakan file Config (misalnya situs web asp.net) https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and- lebih tinggi/

atau di server Anda sendiri https://www.sslshopper.com/iis7-redirect-http-to-https.html

[JAWABAN SINGKAT] Cukup Kode di bawah ini masuk ke dalam

<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
sumber
1

Di IIS10 (Windows 10 dan Server 2016), dari versi 1709 dan seterusnya, ada opsi baru yang lebih sederhana untuk mengaktifkan HSTS untuk situs web.

Microsoft menjelaskan keuntungan dari pendekatan baru di sini , dan memberikan banyak contoh berbeda tentang bagaimana menerapkan perubahan secara terprogram atau dengan secara langsung mengedit file ApplicationHost.config (yang seperti web.config tetapi beroperasi pada tingkat IIS, daripada tingkat situs individu ). ApplicationHost.config dapat ditemukan di C: \ Windows \ System32 \ inetsrv \ config.

Saya telah menjabarkan dua metode contoh di sini untuk menghindari pembusukan tautan.

Metode 1 - Edit file ApplicationHost.config langsung di antara <site>tag, tambahkan baris ini:

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

Metode 2 - Baris Perintah: Jalankan perintah berikut dari prompt perintah yang ditinggikan (yaitu mouse kanan di CMD dan jalankan sebagai administrator). Ingatlah untuk menukar Contoso dengan nama situs Anda seperti yang muncul di 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

Metode lain yang ditawarkan Microsoft dalam artikel itu mungkin pilihan yang lebih baik jika Anda berada di lingkungan yang dihosting di mana Anda memiliki akses terbatas.

Perlu diingat bahwa IIS10 versi 1709 tersedia di Windows 10 sekarang, tetapi untuk Windows Server 2016 ini berada di jalur rilis yang berbeda, dan tidak akan dirilis sebagai paket patch atau layanan. Lihat di sini untuk rincian tentang 1709.

Mike
sumber
0

Jika Anda menggunakan ASP.NET Core, Anda dapat mencoba paket nuget SaidOut.AspNetCore.HttpsWithStrictTransportSecurity.

Maka Anda hanya perlu menambahkan

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

Ini juga akan menambahkan header HTTP StrictTransportSecurity ke semua permintaan yang dibuat menggunakan skema https.

Contoh kode dan dokumentasi https://github.com/saidout/saidout-aspnetcore-httpswithstricttransportsecurity#example-code

pengguna7755300
sumber