2011-12-08 14 views
47

Tôi có ứng dụng python/django trên Heroku (ngăn xếp Cedar) và muốn làm cho ứng dụng có thể truy cập chỉ qua https. Tôi đã kích hoạt "ssl piggyback" -option, và có thể kết nối với nó thông qua https.Làm thế nào để làm cho python trên Heroku https chỉ?

Nhưng cách tốt nhất để vô hiệu hóa quyền truy cập http hoặc chuyển hướng đến https là gì?

Trả lời

63

Kết hợp câu trả lời từ @CraigKerstiens và @allanlei vào nội dung tôi đã thử nghiệm và xác minh để hoạt động. Heroku đặt HTTP_X_FORWARDED_PROTO https khi yêu cầu là ssl, và chúng ta có thể sử dụng để kiểm tra:

from django.conf import settings 
from django.http import HttpResponseRedirect 


class SSLMiddleware(object): 

    def process_request(self, request): 
     if not any([settings.DEBUG, request.is_secure(), request.META.get("HTTP_X_FORWARDED_PROTO", "") == 'https']): 
      url = request.build_absolute_uri(request.get_full_path()) 
      secure_url = url.replace("http://", "https://") 
      return HttpResponseRedirect(secure_url) 
+27

Trả lời bây giờ là một [ứng dụng trên github] (https://github.com/rdegges/django-sslify) –

+1

Upvote để đưa vào github ... Cảm ơn! Chỉ là những gì tôi đang tìm kiếm ngày hôm nay. –

+3

Một lưu ý phụ, điều này không có tác dụng nếu bạn đã đặt DEBUG thành True. Đã dành một giờ để tìm ra điều đó, vì vậy hy vọng điều này sẽ tiết kiệm thời gian cho ai đó. – Femi

6

Bạn đang sử dụng khung làm gì cho ứng dụng của mình? Nếu bạn đang sử dụng Django bạn có thể sử dụng đơn giản một số trung gian tương tự như:

import re 

from django.conf import settings 
from django.core import urlresolvers 
from django.http import HttpResponse, HttpResponseRedirect 


class SSLMiddleware(object): 

    def process_request(self, request): 
     if not any([settings.DEBUG, request.is_secure()]): 
      url = request.build_absolute_uri(request.get_full_path()) 
      secure_url = url.replace("http://", "https://") 
      return HttpResponseRedirect(secure_url) 
+0

Có, tôi đang sử dụng django. Cảm ơn câu trả lời: Tôi sẽ thử nó trừ khi một cái gì đó đơn giản hơn (như một tùy chọn heroku ẩn) xuất hiện .. – Kristian

+0

Tôi đã phải thực hiện một tinh chỉnh nhỏ để bạn trả lời, nhưng người kiểm duyệt đã từ chối chỉnh sửa của tôi. Tôi đã tạo câu trả lời của riêng mình để khắc phục vấn đề với các chuyển hướng không bao giờ kết thúc trong câu trả lời hiện tại của bạn.Cảm ơn anyway, sẽ không bao giờ có suy nghĩ của một giải pháp middleware mà không có sự đóng góp của bạn. – Kristian

+1

Giải pháp này tạo ra một vòng lặp chuyển hướng không bao giờ kết thúc. Xem câu trả lời của tôi ở trên .. – Kristian

13

Không chắc chắn nếu @ CraigKerstiens của câu trả lời sẽ đưa vào tài khoản đó request.is_secure() luôn trả False nếu đằng sau reverse proxy Heroku và không phải là "cố định". Nếu tôi nhớ chính xác, điều này sẽ gây ra một vòng lặp chuyển hướng HTTP.

Nếu bạn đang chạy Django với gunicorn, một cách khác để làm điều đó là để thêm dòng sau vào gunicorn của cấu hình

secure_scheme_headers = { 
    'X-FORWARDED-PROTO': 'https' 
} 

Chạy với một số như thế này trong Procfile

web: python manage.py run_gunicorn -b 0.0.0.0:$PORT -c config/gunicorn.conf 

của bạn Bằng cách đặt của gunicorn secure-scheme-header, request.is_secure() sẽ trả lại đúng số True cho các yêu cầu https. Xem Gunicorn Config.

Bây giờ phần mềm trung gian của @ CraigKerstiens sẽ hoạt động bình thường, bao gồm mọi cuộc gọi đến request.is_secure() trong ứng dụng của bạn.

Lưu ý: Django cũng có cùng cài đặt cấu hình gọi SECURE_PROXY_SSL_HEADER, nhưng trong phiên bản dev.

+2

Cài đặt django SECURE_PROXY_SSL_HEADER hiện khả dụng ở đường chính (chắc chắn trong phiên bản 1.6, có thể sớm hơn). – Symmetric

4

Nếu bạn đang sử dụng Flask, điều này hoạt động khá tốt:

1) Đừng "PIP cài đặt flask- sslify"

(github là ở đây: https://github.com/kennethreitz/flask-sslify)

2) Bao gồm các dòng sau:

from flask_sslify import SSLify 
if 'DYNO' in os.environ: # only trigger SSLify if the app is running on Heroku 
    sslify = SSLify(app) 
+0

Nếu chúng ta làm điều này .... chúng ta vẫn cần phải làm những thứ Heroku? xin lỗi chút mới cho công cụ này – John

+0

Mặc dù xem vấn đề lại "lật-flopping" tại https://github.com/kennethreitz/flask-sslify/issues/3 – wodow

33

Django 1.8 sẽ có hỗ trợ cốt lõi cho phi HTTPS chuyển hướng (tích hợp từ django-secure):

SECURE_SSL_REDIRECT = True # [1] 
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') 

Để SECURE_SSL_REDIRECT được xử lý, bạn phải sử dụng SecurityMiddleware:

MIDDLEWARE = [ 
    ... 
    'django.middleware.security.SecurityMiddleware', 
] 

[1] https://docs.djangoproject.com/en/1.8/ref/settings/#secure-ssl-redirect

+0

Điều này có nghĩa là sslify gói pip là lỗi thời như của Django 1.8? – dfrankow

+0

@dfrankow django-sslify âm thanh tương tự như django-an toàn, nhưng bạn sẽ phải xác nhận rằng với tác giả gói – shangxiao

+0

@ dfrankow Không, bạn vẫn cần sslify với Django 1.8, nếu bạn muốn tự động chuyển hướng người dùng từ http đến https . –

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