Nginx: memaksa SSL di satu jalur, non-SSL di jalur lain

27

Bagaimana cara mengatur file conf Nginx untuk memaksa SSL hanya pada satu jalur di situs saya dan non-SSL di semua yang lainnya?

Sebagai contoh, saya ingin semua URL di bawah / pengguna menjadi https tetapi semua URL lainnya menjadi http.

Untuk bagian pertama yang saya miliki:

rewrite ^/user(.*) https://$http_host$request_uri?;

Saya tidak ingin menggunakan "jika". Saya menganggap itu akan mengambil keuntungan dari urutan operasi tetapi saya tidak ingin berakhir dalam satu lingkaran.

pbreitenbach
sumber

Jawaban:

38

Dalam konfigurasi nginx Anda, Anda harus memiliki dua area "server". Satu untuk port 80, dan satu untuk port 443 (non-SSL dan SSL). Cukup tambahkan lokasi di situs web non-SSL Anda untuk mengalihkan ke halaman SSL Anda.

server {
    root /var/www/
    location / {
    }
    location /user {
        rewrite ^ https://$host$request_uri? permanent;
    }
}

itu akan meneruskan semua lalu lintas yang berakhir di / pengguna ke https Anda: // server.

Kemudian, di server 443 Anda, Anda melakukan yang sebaliknya.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
sumber
2
Pendekatan ini baik, tetapi jatuh ke dalam beberapa Jebakan umum , khususnya "Rooting di dalam blok lokasi" dan "Pajak penulisan ulang"
kolbyjack
1
Saya diedit. Apakah ini terlihat oke? Saya juga mengeluarkan mendengarkan 80 dan menambahkan http_host.
pbreitenbach
Dengan konfigurasi ini, koneksi beralih dari / ke ssl / non-ssl ketika pengguna menavigasi halaman di situs, ssl untuk url dimulai dengan /userdan non-ssl untuk semua url lainnya. Akibatnya, bahkan pengguna secara eksplisit mengetik https://www.example.com/di bilah alamat browser, halaman yang dihasilkan adalah http://www.example.com/. Apakah ada cara untuk mengimplementasikan url-tulis ulang otomatis antara ssl / non-ssl seperti yang dicapai oleh pengaturan yang dijelaskan dalam jawaban ini, tetapi tetap menghormati permintaan ssl eksplisit jika itu secara eksplisit diketik oleh pengguna di bilah alamat? Terima kasih!
selamat tinggal
@ goodbyeera ya. Jika idenya adalah untuk memaksa pengguna untuk menggunakan SSL di area tertentu, kita dapat mengganti protokol mereka di sana tetapi menghormati mereka di tempat lain dengan hanya menghapus perintah penulisan ulang dari konfigurasi server 443. Tentu saja, sekarang ketika mereka pergi ke bagian yang aman, mereka masih akan menjelajah dengan SSL ketika mereka pergi ke tempat lain, tetapi memungkinkan orang untuk memilih untuk menggunakan SSL dari awal.
Chuck Dries
13

Nginx memungkinkan untuk memproses HTTP dan HTTPS dalam serverblok yang sama . Dengan demikian Anda tidak perlu menduplikasi arahan untuk keduanya dan dapat mengarahkan ulang jalur yang ingin Anda amankan

server {
  listen 80 default_server;
  listen 443 ssl;
  ... ssl certificate and other configs ...

  location /user {
    if ($scheme = 'http') {
      rewrite ^ https://$http_host$request_uri? permanent;
    }
  }

  ... your basic configuration ...
}

Pastikan untuk tidak menaruh ssl ongaris di sana karena itu akan merusak HTTP biasa.

Secara opsional, Anda dapat mengalihkan semua permintaan lain dari HTTPS kembali ke HTTP dengan cara yang sama:

if ($scheme = 'https') {
  rewrite ^ http://$http_host$request_uri? permanent;
}

UPDATE : seperti yang ditunjukkan Alexey Ten di bagian komentar, memeriksa schemesetiap permintaan bukanlah ide yang sangat cerdas. Anda harus mengikuti cara deklaratif untuk mengkonfigurasi nginx Anda. Dalam hal ini, deklarasikan dua blok server dengan pengalihan oleh location, pindahkan logika umum ke file yang terpisah dan includekeduanya. Jadi jawaban GruffTech lebih baik.

Hnatt
sumber
2
Tidak efektif membuat skema pemeriksaan nginx untuk setiap permintaan.
Alexey Ten
1
Saya tahu pertanyaan itu dijawab 3 tahun yang lalu, tetapi saya menemukannya ketika berjuang untuk melakukan apa yang secara bertahap saya lakukan dan hanya ingin membagikan hasil saya dengan orang-orang yang akan mengikuti langkah saya.
Hnatt
1
Nah, Anda harus membaca wiki.nginx.org/IfIsEvil
Alexey Ten
1
@ AlexeyTen bukankah itu masalahnya "ketika Anda tidak bisa menghindari menggunakan if"? Apakah ada cara lain untuk memiliki konfigurasi yang sama untuk HTTP dan HTTPS tanpa duplikasi arahan?
Hnatt
2
Gunakan includearahan untuk arahan umum. Beberapa duplikasi OK.
Alexey Ten