2013-02-27 21 views
7

Quando tento di reindirizzare il traffico in arrivo su https, ottengo un ciclo di reindirizzamento infinito.Reindirizza HTTP a HTTPS su 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']) 

Il request.url non viene mai modificato al prefisso https. Voglio usare il slyl piggyback di heroku per minimizzare i costi.

risposta

6

Su Heroku, SSL (https) viene interrotto prima che raggiunga l'applicazione, quindi l'app non vede mai effettivamente il traffico SSL. Per verificare se è stata effettuata una richiesta con https, devi invece ispezionare l'intestazione x-forwarded-proto. Maggiori informazioni qui: How to make python on Heroku https only?

AGGIORNAMENTO: Per l'utilizzo, è sufficiente controllare request.url per "myapp.herokuapp.com/checkout/"; e verificare che l'intestazione sia "https"

+0

Grazie friism. Ho visto il pacchetto flask-sslify. Che soddisferebbe le mie esigenze, tranne che sto usando un dominio personalizzato insieme al sottodominio di heroku. Voglio solo mettere SSL su una pagina. Grazie per il doc comunque, lo leggerò. –

+0

Dovresti semplicemente controllare 'request.url' per" http://myapp.herokuapp.com/checkout/ "e verificare che l'intestazione sia" https " – friism

+1

Grazie, ecco cosa ha fatto. –

0

Sono riuscito a riutilizzare il codice di flask-sslify per una singola vista. Serve solo per verificare se la richiesta è stata effettuata o meno con SSL e aggiungere intestazioni appropriate alla risposta. 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) Evitare "PIP installare pallone-sslify"

(GitHub è qui: https://github.com/kennethreitz/flask-sslify)

2) Includere le seguenti righe:

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

Il '' DYNO 'nel suggerimento os.environ' è particolarmente utile. – awm

+0

Si noti che funziona solo se 'app.debug = False' – tdc

4

ho provato SSLify , url_for _scheme e impostazione di PREFERRED_URL_SCHEME; comunque nessuno ha funzionato, almeno al livello di rilascio .. (funzionava bene localmente) Poi ho pensato;

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

Questo è essenzialmente un altro modo per farlo senza configurazioni o estensioni.

+1

Questo ha provocato" Questa pagina web ha un ciclo di reindirizzamento "per me – tdc

+0

@tdc Interessante, hai provato la risposta che ho dato prima che qualcuno abbia modificato questa risposta? Non ho provato questo, anche se sembra che dovrebbe funzionare allo stesso modo; So che l'originale ha funzionato sicuramente bene. – Miles

+0

Non ho mai visto l'originale! SSLify ha funzionato per me alla fine – tdc

0

Hai solo bisogno di controllare l'intestazione X-Forwarded-Proto. Se è falso, reindirizza all'URL https equivalente.

Ecco il codice per far rispettare https per tutte le chiamate su un'applicazione in esecuzione sul pallone 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) 
Problemi correlati