python - Flask SecureCookie用json替换pickle导致编码错误

标签 python session flask werkzeug

下面是 werkzeug 对 session 序列化的建议:

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:

当我按照下面的 Flask 实现执行此操作时:

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

或者

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

当我尝试登录时会发生这种情况。

我深入研究了 json 编码器源并尝试设置 ensure_ascii=False,这让我克服了上面的错误,但后来我根本无法登录应用程序。它只会毫无错误地闪烁屏幕,我仍然停留在登录提示符处。使用 pickle 一切正常。

一个重要的旁注,这个问题是 Flask-login 集成所独有的,并且不会仅在普通 flask session 序列化中发生

ASKSBADQUESTIONS 的代码确实有效,但这会引发解码错误

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)

这是堆栈跟踪

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

最佳答案

flask_login.py 中有一个名为_create_identifier 的方法。此调用的结果是 md5 digest() 结果。根据文档,这可以包含非 ascii 字符和/或空字节。当交给 serialization_method 时,它无法解码 unicode 字节。

这个错误肯定存在于 Flask 0.9 和 Flask-login 0.1.3 的组合中,可以通过猴子修补这个要点(https://gist.github.com/anonymous/3731115)到 flask_login.py 文件中来修复,或者你可以从开发中提取最新的。

如果您需要更多信息,可以在他们的 github repo 上引用这个错误 https://github.com/maxcountryman/flask-login/pull/31

关于python - Flask SecureCookie用json替换pickle导致编码错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15580476/

相关文章:

session - Express.js req.session 变量不通过不同的路由存储 session 变量

python - 无需 Celery 或 Redis 即可进行进度跟踪的后台任务

python - keras 模型会影响输入数据的大小吗?

python - 正则表达式中的最后一个匹配符号

python - 不受信任的用户不应运行哪些内置函数?

python - 来自 Scopus API 的请求仅写入 PDF 的第一页

web-services - 关于 Rest "Communicate statelessly"原理

django - 如何创建一个在 Django 登录时设置 session 变量的中间件?

python - Flask 配置文件 - 'DEBUG=True' 什么都不做

python - Flask、蓝图、current_app