2013-02-27 66 views
7

Khi tôi cố gắng chuyển hướng lưu lượng truy cập đến https tôi nhận được vòng lặp chuyển hướng vô hạn.Chuyển hướng HTTP sang HTTPS trên Flask + Heroku

@app.route('/checkout/')                                               
def checkout():                                                 
    checkout = "https://myapp.herokuapp.com/checkout/"                                    
    if checkout != request.url:                                            
     print checkout, request.url                                            
     return redirect(checkout)                                            
    return render_template('checkout.html', key=keys['publishable_key']) 

Yêu cầu.url không bao giờ được đổi thành tiền tố https. Tôi muốn sử dụng sgy piggyback của heroku để giảm thiểu chi phí.

Trả lời

6

Trên Heroku, SSL (https) bị chấm dứt trước khi nó đến ứng dụng của bạn, vì vậy ứng dụng của bạn không bao giờ thực sự thấy lưu lượng truy cập SSL. Để kiểm tra xem yêu cầu đã được thực hiện với https chưa, bạn thay vào đó phải kiểm tra tiêu đề x-forwarded-proto. Thông tin thêm tại đây: How to make python on Heroku https only?

CẬP NHẬT: Để sử dụng, bạn chỉ cần kiểm tra request.url cho "myapp.herokuapp.com/checkout/"; và xác minh rằng tiêu đề là "https"

+0

Cảm ơn friism. Tôi đã thấy gói sslify bình. Mà sẽ đáp ứng nhu cầu của tôi, ngoại trừ tôi đang sử dụng một tên miền tùy chỉnh cùng với tên miền phụ của heroku. Tôi chỉ muốn đặt SSL trên một trang. Cảm ơn các tài liệu mặc dù, tôi sẽ đọc qua nó. –

+0

Bạn chỉ cần kiểm tra 'request.url' cho" http://myapp.herokuapp.com/checkout/ "và xác minh rằng tiêu đề là" https " – friism

+1

Cảm ơn, đó là những gì đã làm. –

0

Tôi đã có thể sử dụng lại mã sslify bình cho một lượt xem. Chỉ cần kiểm tra xem yêu cầu có được thực hiện với SSL hay không và thêm tiêu đề thích hợp vào phản hồi. https://github.com/kennethreitz/flask-sslify

@app.route('/checkout/')                                               
def checkout():                                                 
    checkout = "https://myapp.herokuapp.com/checkout/"                                    
    if request.headers.get('X-Forwarded-Proto', 'http') == 'https':                                    
     resp = make_response(render_template('checkout.html', key=keys['publishable_key']))                            
     return set_hsts_header(resp)                                            
    return redirect(checkout, code=302)                                           

def set_hsts_header(response):                                             
    """Adds HSTS header to each response."""                                          
    response.headers.setdefault('Strict-Transport-Security', hsts_header)                                  
    return response                                                

def hsts_header():                                                
    """Returns the proper HSTS policy."""                                          
    hsts_policy = 'max-age={0}'.format(31536000) #year in seconds                                    
    if self.hsts_include_subdomains:                                            
     hsts_policy += '; includeSubDomains'                                          
     return hsts_policy 
10

1) Đừng "PIP cài đặt bình-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

Mẹo '' DYNO 'trong os.environ' đặc biệt hữu ích. – awm

+0

Lưu ý rằng nó chỉ hoạt động nếu 'app.debug = False' – tdc

4

tôi đã cố gắng SSLify , url_for _scheme và đặt PREFERRED_URL_SCHEME; Tuy nhiên không ai làm việc ra, ở mức độ phát hành ít nhất .. (làm việc tốt tại địa phương) Sau đó, tôi nghĩ;

@app.before_request 
def beforeRequest(): 
    if not request.url.startswith('https'): 
     return redirect(request.url.replace('http', 'https', 1)) 

Đây thực chất là một cách khác để hoàn thành công việc mà không cần bất kỳ cấu hình hoặc tiện ích nào.

+1

Điều này dẫn đến" Trang web này có vòng chuyển hướng "cho tôi – tdc

+0

@tdc Thú vị, bạn đã thử câu trả lời tôi đưa ra trước khi ai đó chỉnh sửa câu trả lời này chưa? Tôi đã không thử điều này, mặc dù có vẻ như nó sẽ làm việc như nhau; Tôi biết bản gốc chắc chắn đã làm việc tốt. – Miles

+0

Tôi chưa bao giờ thấy bản gốc! SSLify đã làm việc cho tôi cuối cùng – tdc

0

Bạn chỉ cần kiểm tra tiêu đề X-Forwarded-Proto. Nếu sai, chuyển hướng đến url https tương đương.

Đây mã để thực thi https cho tất cả các cuộc gọi trên một ứng dụng bình chạy trên Heroku:

@app.before_request 
def enforceHttpsInHeroku(): 
    if request.headers.get('X-Forwarded-Proto') == 'http': 
    url = request.url.replace('http://', 'https://', 1) 
    code = 301 
    return redirect(url, code=code) 
Các vấn đề liên quan