【问题标题】:Flask SecureCookie replacing pickle with json results in encoding errorFlask SecureCookie 用 json 替换 pickle 会导致编码错误
【发布时间】:2013-03-22 21:54:39
【问题描述】:

以下是 werkzeug 对会话序列化的建议:

默认实现使用 Pickle,因为这是唯一的模块 曾经在该模块发布时在标准库中可用 创建的。如果您有 simplejson 可用,强烈建议您使用 创建子类并替换序列化方法:

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

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

或者

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

UnicodeDecodeError:“utf8”编解码器无法解码位置 0 中的字节 0x97: 无效的起始字节

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

我已经深入研究了 json 编码器源并尝试设置 ensure_ascii=False,这让我克服了上面的错误,但是我根本无法登录应用程序。它只会闪烁屏幕而没有错误,我仍然停留在登录提示符下。泡菜一切正常。

一个重要的侧面说明这个问题是 Flask-login 的集成所独有的,并且不会发生在普通的 flask 会话序列化中

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

【问题讨论】:

    标签: python session flask werkzeug


    【解决方案1】:

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

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

    如果你需要更多信息,你可以在他们的 github repo 上参考这个 bug https://github.com/maxcountryman/flask-login/pull/31

    【讨论】:

      【解决方案2】:

      我快速编写了最小的 Flask 应用程序来重现您的错误(保存到 app.py;使用 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)
      

      但一切都很顺利。我什至将session_interface 从基于 Pickle 的更改为基于 JSON 的几次,并且没有出现异常。也许您应该发布完整的异常回溯并(也许)在我的示例中添加一些代码来重现错误。

      【讨论】:

      • 于是我继续试验。我把你的代码放在那里,它工作正常。然后,我逐步将您的代码集成到我的代码中。我发现我从 Flask-Login 扩展初始化登录管理器的那一刻就是我开始收到错误的时候。
      • 因此,如果您查看我上面的示例,您会发现它似乎是集成 Flask-login 模块所独有的
      猜你喜欢
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      相关资源
      最近更新 更多