Nginx: บังคับให้ SSL บนเส้นทางเดียวไม่ใช่ SSL กับผู้อื่น


27

ฉันจะตั้งค่าไฟล์ Nginx conf ให้บังคับ SSL บนเส้นทางเดียวในเว็บไซต์ของฉันและไม่ใช่ SSL ในส่วนที่เหลือทั้งหมดได้อย่างไร

ตัวอย่างเช่นฉันต้องการให้ URL ทั้งหมดภายใต้ / user เป็น https แต่ URL ที่เหลือทั้งหมดจะเป็น http

สำหรับส่วนแรกฉันมี:

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

ฉันไม่ต้องการใช้ "ถ้า" ฉันคิดว่ามันจะใช้ประโยชน์จากลำดับการดำเนินการ แต่ฉันไม่ต้องการที่จะจบลงด้วยการวนซ้ำ

คำตอบ:


38

ในการกำหนดค่า nginx ของคุณคุณควรมีสองส่วน "เซิร์ฟเวอร์" หนึ่งพอร์ต 80 และอีกพอร์ตสำหรับ 443 (ไม่ใช่ SSL และ SSL) เพียงเพิ่มที่ตั้งในเว็บไซต์ที่ไม่ใช่ SSL ของคุณเพื่อเปลี่ยนเส้นทางไปยังหน้า SSL ของคุณ

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

มันจะส่งต่อการรับส่งข้อมูลทั้งหมดที่สิ้นสุดที่ / ผู้ใช้ไปยังเซิร์ฟเวอร์ https: // ของคุณ

จากนั้นในเซิร์ฟเวอร์ 443 ของคุณคุณทำตรงกันข้าม

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

2
วิธีการนี้เป็นสิ่งที่ดี แต่มันตกลงไปในข้อผิดพลาดทั่วไปสองอย่างโดยเฉพาะ "รูทด้านในบล็อกสถานที่ตั้ง" และ "การเขียนเรื่องภาษี"
kolbyjack

1
ฉันแก้ไข มันดูโอเคไหม ฉันยังเอาฟัง 80 และเพิ่ม http_host
pbreitenbach

ด้วยการกำหนดค่านี้การเชื่อมต่อจะเปลี่ยนจาก / เป็น ssl / non-ssl เมื่อผู้ใช้นำทางไปยังหน้าต่างๆในเว็บไซต์ ssl สำหรับ URL ที่เริ่มต้นด้วย/userและไม่ใช่ ssl สำหรับ URL อื่น ๆ ทั้งหมด เป็นผลให้ผู้ใช้ยังชัดเจนชนิดในแถบที่อยู่ของเบราว์เซอร์หน้าผลลัพธ์คือhttps://www.example.com/ http://www.example.com/มีวิธีการนำ auto-url-rewrite ระหว่าง ssl / non-ssl มาใช้โดยการตั้งค่าที่อธิบายไว้ในคำตอบนี้ แต่ยังคงเคารพคำขอ ssl ที่ชัดเจนหากผู้ใช้พิมพ์ลงในแถบที่อยู่อย่างชัดเจนหรือไม่ ขอบคุณ!
ลาก่อน

@ goodbyeera ใช่ หากแนวคิดคือการบังคับให้ผู้ใช้ใช้ SSL ในบางพื้นที่เราสามารถแทนที่โปรโตคอลของพวกเขาที่นั่น แต่ให้เกียรติพวกเขาทุกที่อื่นโดยเพียงแค่ลบคำสั่งเขียนใหม่จากการกำหนดค่าเซิร์ฟเวอร์ 443 แน่นอนตอนนี้เมื่อพวกเขาไปที่ส่วนที่ปลอดภัยพวกเขาจะยังคงค้นหาด้วย SSL เมื่อพวกเขาไปที่อื่น แต่ช่วยให้ผู้ใช้สามารถเลือกใช้ SSL จากการเดินทาง
Chries Dries

13

Nginx อนุญาตให้ประมวลผลทั้ง HTTP และ HTTPS ภายในserverบล็อกเดียวกัน ดังนั้นคุณไม่จำเป็นต้องทำซ้ำคำสั่งทั้งคู่และสามารถเปลี่ยนเส้นทางที่คุณต้องการรักษาความปลอดภัย

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

ตรวจสอบให้แน่ใจว่าไม่ได้วางssl onบรรทัดไว้เพราะจะทำให้ HTTP ธรรมดาเสีย

คุณสามารถเปลี่ยนเส้นทางคำขออื่น ๆ ทั้งหมดจาก HTTPS กลับไปที่ HTTP ในลักษณะเดียวกันได้:

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

ปรับปรุง : เป็น Alexey Ten กรุณาชี้ให้เห็นในส่วนความเห็นการตรวจสอบschemeคำขอแต่ละครั้งไม่ได้เป็นความคิดที่สดใสมาก คุณควรทำตามวิธีการกำหนดค่า nginx ของคุณ ในกรณีนี้ให้ประกาศเซิร์ฟเวอร์สองบล็อกด้วยการเปลี่ยนเส้นทางlocationย้ายตรรกะทั่วไปไปยังไฟล์แยกและincludeทั้งสองอย่าง ดังนั้นคำตอบของ GruffTech จึงดีกว่า


2
มันไม่มีประสิทธิภาพที่จะทำให้รูปแบบการตรวจสอบ nginx สำหรับทุกคำขอ
Alexey Ten

1
ฉันรู้ว่าคำถามนั้นได้รับคำตอบเมื่อ 3 ปีที่แล้ว แต่ฉันพบว่าในขณะที่พยายามทำสิ่งที่ฉันทำไปเรื่อย ๆ และต้องการแบ่งปันผลลัพธ์กับคนที่จะทำตามขั้นตอนของฉัน
Hnatt

1
คุณควรอ่านwiki.nginx.org/IfIsEvil
Alexey Ten

1
@AlexeyTen ไม่ใช่กรณี "เมื่อคุณไม่สามารถหลีกเลี่ยงการใช้ if" มีวิธีอื่นในการตั้งค่าเดียวกันสำหรับ HTTP และ HTTPS โดยไม่ทำซ้ำคำสั่งหรือไม่
Hnatt

2
ใช้includeคำสั่งสำหรับคำสั่งทั่วไป การทำสำเนาบางอย่างก็โอเค
Alexey Ten
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.