2013-04-26 15 views
9

Sto cercando di ottenere correttamente Flask per gestire lo scripting cross-site. Ho preso il frammento di decoratore crossdomain da qui: http://flask.pocoo.org/snippets/56/Python Flask cross site HTTP POST - non funziona per origini specifiche consentite

Nel codice qui sotto, ho messo il frammento di decoratore e il server fiasco di base.

Sto chiamando il decoratore con intestazioni = 'Content-Type' perché altrimenti stavo ottenendo "Richiesto campo di intestazione Content-Type non consentito da Access-Control-Allow-Headers." nel browser.

Quindi, ecco la mia domanda: Così com'è, il codice sotto funziona. Ma quando voglio limitare solo a un server specifico in questo modo:

@crossdomain(origin='myserver.com', headers='Content-Type') 

ottengo l'errore del browser

"Origine http://myserver.com non è consentito da Access-Control-Allow-Origin."

Non riesco a farlo funzionare per qualcosa di diverso da origine = '*'.

Qualcuno ha qualche idea?

Ecco il codice completo:

from datetime import timedelta 
from flask import make_response, request, current_app, Flask, jsonify 
from functools import update_wrapper 

def crossdomain(origin=None, methods=None, headers=None, 
      max_age=21600, attach_to_all=True, 
      automatic_options=True): 
    if methods is not None: 
     methods = ', '.join(sorted(x.upper() for x in methods)) 
    if headers is not None and not isinstance(headers, basestring): 
     headers = ', '.join(x.upper() for x in headers) 
    if not isinstance(origin, basestring): 
     origin = ', '.join(origin) 
    if isinstance(max_age, timedelta): 
     max_age = max_age.total_seconds() 

    def get_methods(): 
     if methods is not None: 
      return methods 

     options_resp = current_app.make_default_options_response() 
     return options_resp.headers['allow'] 

    def decorator(f): 
     def wrapped_function(*args, **kwargs): 
      if automatic_options and request.method == 'OPTIONS': 
      resp = current_app.make_default_options_response() 
      else: 
       resp = make_response(f(*args, **kwargs)) 
      if not attach_to_all and request.method != 'OPTIONS': 
       return resp 

      h = resp.headers 

      h['Access-Control-Allow-Origin'] = origin 
      h['Access-Control-Allow-Methods'] = get_methods() 
      h['Access-Control-Max-Age'] = str(max_age) 
      if headers is not None: 
       h['Access-Control-Allow-Headers'] = headers 
      return resp 

     f.provide_automatic_options = False 
     return update_wrapper(wrapped_function, f) 
    return decorator 

app = Flask(__name__) 

@app.route('/my_service', methods=['POST', 'OPTIONS']) 
@crossdomain(origin='*', headers='Content-Type') 
def my_service(): 
    return jsonify(foo='cross domain ftw') 

if __name__ == '__main__': 
    app.run(host="0.0.0.0", port=8080, debug=True) 

Per riferimento mia versione 2.7.2 pitone è versione 0.7.2 pallone viene

risposta

2

Ho appena provato lo stesso codice con Python versione 2.7.3 e Flask versione 0.8.

Con queste versioni, non riesce con

@crossdomain(origin='myserver.com', headers='Content-Type') 

ma funziona con

@crossdomain(origin='http://myserver.com', headers='Content-Type') 

Forse semplicemente non funziona con la boccetta 0.7.2? (nonostante quello che dice sulla pagina snippet).


EDIT: Dopo aver giocato con questo molto di più (e l'aggiornamento a Boccetta 0.9) sembra che il vero problema (o di un altro problema) potrebbero essere collegati ad avere origini multiple consentite in un elenco. In altre parole, utilizzando il codice precedente come questo:

@crossdomain(origin=['http://myserver.com', 'http://myserver2.com'], headers='Content-Type') 

non funziona.

Per risolvere questo problema ho ottimizzato il decoratore. Vedere il codice qui: http://chopapp.com/#351l7gc3

Questo codice restituisce solo il dominio del sito richiedente se è presente nell'elenco. Un po 'bizzarro, ma almeno per me, problema risolto :)

+0

cant vedere il codice – martriay

+0

E 'lì, ma per qualche ragione di prendere un po' a carico. – Nate

+0

Re il tuo codice: nota che request.headers ['Origin'] può essere None, e l'operatore 'in' non può accettare None come argomento di sinistra. Altrimenti, grazie :-) –

0

Python si sta impegnando a fondo per impedirti di esporsi a attacchi cross-site scripting.

Una correzione è arrendendosi e facendo sì che le richieste colpiscano lo stesso server su cui è in esecuzione lo script.Recuperare JSON da server lontani definiti nelle stringhe è comunque un'attività rischiosa.

sono stato in grado di risolvere il problema lasciando il browser mantenersi sullo stesso server, in questo modo:

$('a#calculate').bind('click', function() { 
    $.getJSON('/_add_numbers', { 
    a: $('input[name="a"]').val(), 
    b: $('input[name="b"]').val() 
    }, function(data) { 
    $("#result").text(data.request); 
    }); 
    return false; 
}); 

Si noti come metodo getJSON viene passato un /_add_numbers. Ciò comunica al browser di rimanere sullo stesso host e cercare quella pagina. Poi il browser è felice e sicuro abbiamo deciso di restare sullo stesso host, e non si ha mai l'errore:

Origin http://myserver.com is not allowed by Access-Control-Allow-Origin 
Problemi correlati