2013-03-22 12 views
6

seguito è la raccomandazione di werkzeug per la sessione di serializzazione:Flask SecureCookie sostituzione salamoia con risultati JSON in errore codifica

The default implementation uses Pickle as this is the only module that used to be available in the standard library when this module was created. If you have simplejson available it’s strongly recommended to create a subclass and replace the serialization method:

Quando faccio questo a seguito sia l'attuazione Flask di seguito:

https://gist.github.com/runfalk/2501926

o, in alternativa

from werkzeug.contrib.securecookie import SecureCookie 
Secure_Cookie.serialization_method = json 

UnicodeDecodeError: 'utf8' codec can't decode byte 0x97 in position 0: invalid start byte

Ciò accade quando tento di accedere.

Mi sono immerso nella sorgente dell'encoder JSON e ho tentato di impostare ensure_ascii=False e questo mi ha superato l'errore sopra ma poi non sono riuscito a collegarmi all'applicazione. Avrebbe semplicemente lampeggiato lo schermo senza errori e sono rimasto bloccato al prompt di login. Con il sottaceto tutto funziona bene.

Un importante nota a margine di questo problema è unico per l'integrazione del Flask-login e non si verifica solo con la vaniglia flask sessione di serializzazione codice

di ASKSBADQUESTIONS effettivamente funziona, ma questo genera l'errore di decodifica

import json 

from flask import Flask, session 
from flask.sessions import SecureCookieSession, SecureCookieSessionInterface 
from flask.ext.login import LoginManager 

class JSONSecureCookieSession(SecureCookieSession): 
    serialization_method = json 

class JSONSecureCookieSessionInterface(SecureCookieSessionInterface): 
    session_class = JSONSecureCookieSession 

app = Flask(__name__) 
app.secret_key = "I-like-cookies-and-some-secure-cookies" 
app.session_interface = JSONSecureCookieSessionInterface() 

#Initialize Login Manager 
login_manager = LoginManager() 
login_manager.setup_app(app) 

@app.route("/") 
def hello(): 
    k = "lalala" 

    v = session.get(k) 

    if v is None: 
     print "set" 
     v = session[k] = "FLAAASK abuses decorators in a bad way :)" 
    else: 
     print "get" 

    return "Hello {0}".format(v) 


if __name__ == "__main__": 
    app.run(debug=True) 

E qui è lo stacktrace

Traceback (most recent call last): 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app 
    response = self.make_response(self.handle_exception(e)) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 1362, in full_dispatch_request 
    response = self.process_response(response) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 1566, in process_response 
    self.save_session(ctx.session, response) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/app.py", line 804, in save_session 
    return self.session_interface.save_session(self, session, response) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/flask/sessions.py", line 205, in save_session 
    secure=secure, domain=domain) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/werkzeug/contrib/securecookie.py", line 329, in save_cookie 
    data = self.serialize(session_expires or expires) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/werkzeug/contrib/securecookie.py", line 235, in serialize 
    self.quote(value) 
    File "/usr/local/pythonbrew/venvs/Python-2.7.3/flask-session-bug/lib/python2.7/site-packages/werkzeug/contrib/securecookie.py", line 192, in quote 
    value = cls.serialization_method.dumps(value) 
    File "/usr/local/pythonbrew/pythons/Python-2.7.3/lib/python2.7/json/__init__.py", line 231, in dumps 
    return _default_encoder.encode(obj) 
    File "/usr/local/pythonbrew/pythons/Python-2.7.3/lib/python2.7/json/encoder.py", line 195, in encode 
    return encode_basestring_ascii(o) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0x97 in position 0: invalid start byte 
set 

risposta

3

C'è un metodo in flask_login.py chiamato _create_identifier. Il risultato di questa chiamata è un risultato md5 digest(). Secondo i documenti questo può contenere caratteri non ascii e/o byte null. Quando viene consegnato allo serialization_method non è in grado di decodificare i byte unicode.

Questo errore esiste sicuramente nella combinazione di Flask 0.9 e Flask-login 0.1.3 e può essere risolto da scimmia che applica questo elenco (https://gist.github.com/anonymous/3731115) nel file flask_login.py o è possibile estrarre l'ultimo sviluppo.

è possibile fare riferimento a questo bug sul loro repo github se avete bisogno di maggiori informazioni https://github.com/maxcountryman/flask-login/pull/31

1

Ho scritto rapidamente l'app Flask minima per riprodurre il bug (salvato in app.py; invocato con python app.py):

import json 

from flask import Flask, session 
from flask.sessions import SecureCookieSession, SecureCookieSessionInterface 


class JSONSecureCookieSession(SecureCookieSession): 
    serialization_method = json 


class JSONSecureCookieSessionInterface(SecureCookieSessionInterface): 
    session_class = JSONSecureCookieSession 


app = Flask(__name__) 
app.secret_key = "I-like-cookies-and-some-secure-cookies" 
app.session_interface = JSONSecureCookieSessionInterface() 


@app.route("/") 
def hello(): 
    k = "lalala" 

    v = session.get(k) 

    if v is None: 
     print "set" 
     v = session[k] = "FLAAASK abuses decorators in a bad way :)" 
    else: 
     print "get" 

    return "Hello {0}".format(v) 


if __name__ == "__main__": 
    app.run(debug=True) 

Ma tutto è andato liscio. Ho persino cambiato session_interface da base di Pickle a JSON poche volte, e non ho ottenuto eccezioni. Forse dovresti postare la traceback completa delle eccezioni e (forse) aggiungere del codice al mio esempio per riprodurre un bug.

+0

così ho continuato a sperimentare. Ho lasciato cadere il tuo codice e funziona perfettamente. Ho quindi integrato il tuo codice nel mio passo-passo. Quello che ho trovato è il momento in cui inizializzo il login manager dall'estensione Flask-Login quando inizio a ricevere l'errore. – nsfyn55

+0

Quindi, se si controlla il mio esempio sopra, si vede che sembra essere univoco integrare il modulo Flask-login – nsfyn55