2012-03-15 27 views
5

Tôi có máy chủ Express.js (v 2.5.8) (nút v0.6.12) chạy trên cổng 3100. Nó là mặt trước được Nginx kết thúc, ủy quyền cả yêu cầu http và https đến cổng 3100.Yêu cầu lực lượng trên https trong Express/Node

Tôi muốn buộc một số url nhất định trên https. Dưới đây là một ví dụ (ứng dụng là máy chủ Express):

app.get('/applyNow', ensureSec, secure.showApplication); 

ensureSec là chức năng mà tôi đang cố gắng để sử dụng để kiểm tra xem kết nối qua ssl:

function ensureSec(req, res, next) { 
    if (req.session.ssl == true) { 
     return next(); 
    } else { 
     req.session.ssl = true; 
     res.redirect('https://' + url.parse(req.headers.referer).host + 
     url.parse(req.url).pathname); 
    } 
} 

Các công trình chuyển hướng nhưng nút (sau khi nó hết thời gian) ném một lỗi nói rằng 'Không thể GET/applyNow

Cách chuyển hướng thích hợp đến ssl là gì?

Trả lời

6

Như tôi đã hiểu, bạn đang sử dụng nginx để thương lượng SSL và ủy quyền cả yêu cầu http và https cho ứng dụng Express của bạn. Thay vào đó, tôi sẽ chọn giải pháp này trong nginx, nếu có thể, nhưng nếu nginx không thể biết đường dẫn nào cần được bảo vệ (nghĩa là chỉ có sẵn qua https) hoặc bạn muốn thực hiện điều này trong ứng dụng nhanh của mình vì một số lý do khác, dưới đây là một số thông tin:

Bạn sẽ nhận được X-Forwarded-Proto từ nginx, được đặt thành https chỉ khi giao thức ban đầu là https.Đây là cách bạn làm điều này trong nginx:

proxy_set_header X-Forwarded-Proto https; 

Tôi cũng xin chuyển tiếp Host tiêu đề:

proxy_set_header Host $http_host; 

Trong ứng dụng rõ ràng của bạn, kiểm tra cho rằng, hoặc chuyển hướng đến các máy chủ trong các tiêu đề và các yêu cầu đường dẫn (nhanh phân tích đó để req.path vì vậy bạn không cần phải):

function ensureSec(req, res, next) { 
    if (req.headers['x-forwarded-proto'] == 'https') { 
     return next(); 
    } else { 
     res.redirect('https://' + req.headers.host + req.path); 
    } 
} 
+0

Điều này trông giống như giải pháp phù hợp với tôi. Cảm ơn! –

+0

Tiêu đề X-Forwarded-Proto thực sự là một viên ngọc ẩn. Cố định nó, cảm ơn. –

0

Bạn cần 2 đối tượng thể hiện khác nhau app để thực hiện việc này. Mỗi thể hiện của một máy chủ tốc hành chỉ có thể nghe chính xác một giao thức tại một thời điểm. Tất cả điều này có thể ở trong một quá trình node.js, nhưng bạn cần 2 máy chủ tốc hành được cấu hình khác nhau app trường hợp, một cho http và một cho https. Xem câu trả lời của tôi cho một ví dụ:

How to force SSL/https in Express.js

Xem thêm: Automatic HTTPS connection/redirect with node.js/express?

Cũng lưu ý rằng bạn không nên chỉ định req.session.ssl. Việc thiết lập điều đó thành true không thực sự kỳ diệu làm cho nó giống như là máy khách đã kết nối với TLS thay vì HTTP rõ ràng. Đó là thuộc tính chỉ đọc. Gán nó không có hiệu lực.

Bạn cũng nên lưu ý rằng bạn không thể chạy cả http và https trên một cổng. Đó là lý do tại sao http sử dụng 80 và https sử dụng 443.

Khi bạn gặp lỗi Cannot GET /applyNow, điều đó có nghĩa là các tuyến đường tốc hành của bạn không bao giờ khớp với đường dẫn yêu cầu và do đó không bao giờ được gọi là phần mềm trung gian ensureSec.

+0

Tôi đang sử dụng Nginx. Nginx có thể xử lý cả các kết nối http và https để tôi có thể tải nó khỏi ứng dụng của tôi. Tôi chỉ cần lực lượng một số đường dẫn để chạy trên ssl. –

+0

Một lần nữa, bạn cần 2 cổng khác nhau và 2 phiên bản ứng dụng thể hiện khác nhau. Có thật không. Điều này tất cả có thể là một quá trình node.js và bạn có thể buộc một số đường dẫn http chuyển hướng đến https, nhưng bạn không thể chạy 2 giao thức hoàn toàn khác nhau như http và https trên cùng một cổng cùng một lúc. Đó không phải là giới hạn của node.js, đó là cách các giao thức được thiết kế. –

+0

Peter, như tôi đã hiểu câu hỏi, Rob có một máy chủ nginx ở phía trước, ủy quyền các yêu cầu đến một máy chủ node.js. Vì vậy, với ứng dụng tốc hành, tất cả các yêu cầu sẽ là http. Nhưng một số đường dẫn, Rob không muốn máy chủ tốc hành xử lý trừ khi đó là yêu cầu https (tới nginx). Tôi sẽ đề nghị thực thi điều này trong nginx thay vào đó, mà có vẻ đơn giản hơn nhiều. Ngoài ra, sự hiểu biết của tôi là Rob sử dụng 'req.session.ssl' để theo dõi xem khách hàng có kết nối thông qua https hay không, điều này có vẻ không ổn định (bạn cần đặt lại trong trường hợp thích hợp). –

0

Bạn có thể định cấu hình cổng ssl trên máy chủ nginx và các yêu cầu proxy của mình thành node.js như các yêu cầu khác.

http://nginx.org/en/docs/http/configuring_https_servers.html

Không cần phải thay đổi ứng dụng Node.js. Chỉ cần cấu hình 443 cổng trên nginx với các chứng chỉ và các yêu cầu proxy của bạn đến ứng dụng node.js.

+0

Cảm ơn. Tôi đã làm như vậy. Tôi chỉ muốn bảo vệ những con đường nhất định. Tôi muốn làm như vậy trong ứng dụng nút thay vì trong nginx. Làm như vậy giúp triển khai dễ dàng hơn. –

0

Để thêm vào những gì Peter Lyons đã nói, hãy thể hiện các nhiệm vụ mà bạn chỉ chạy một máy chủ trên một cổng. Nếu bạn cố gắng chạy hai máy chủ http trên một cổng, nó sẽ ném một lỗi EADDRINUSE.

+0

Có, cảm ơn bạn. –

0

Như bạn đang sử dụng Nginx trên front-end, cách sạch nhất và đơn giản nhất để đạt được điều này là để chuyển tiếp (viết lại) http URL trong Nginx để HTTPS thay vì cố gắng để chuyển hướng trong Express. Điều này có thể được thực hiện như sau:

server { 
    listen 12.34.56.78:80; 
    server_name yourserver.com; 

    location/{ 
     rewrite^https://$server_name$request_uri permanent; 
    } 
} 

Bạn có thể viết lại với dòng này:

rewrite^https://ducklington.org$request_uri permanent; 

Chỉ cần thiết lập vị trí của bạn để phù hợp với các tuyến đường hay tắc mà bạn cần để chuyển tiếp đến https.

0

app.enable ('trust proxy');

"Sử dụng Express phía sau proxy ngược như Varnish hoặc Nginx là nhỏ, tuy nhiên nó yêu cầu cấu hình. Bằng cách bật cài đặt" ủy thác proxy "thông qua app.enable ('trust proxy'), Express sẽ biết rằng ngồi sau một proxy và các trường tiêu đề X-Forwarded- * có thể được tin cậy, nếu không có thể dễ bị giả mạo. "

Express behind proxies doco

Các vấn đề liên quan