python - 在 Flask 中建立持久化复杂对象的正确方法

标签 python flask

我正在寻找有关如何在 Flask 中处理持久对象的“最佳实践”建议。

我有自己的类来处理用户、组、组中的用户成员身份和用户/组权限。其中,有一个 Passport 类保存有关当前用户及其权限的信息。

这个想法是,每个用户 session 都应该与其自己的 Passport 对象相关联,该对象在 View 上持久存在:以便可以在用户登录时初始化某些权限,并且可以在以后使用 View 和执行 AJAX 请求时进行检查。

目前我在 Passport 类中有序列化和反序列化方法,还有一个在 views.py 全局范围内初始化的 FlaskPassport 类,它有一个只读的“护照”属性,可以从 session 变量中读取序列化的护照数据并返回反序列化的对象。它有一个 save() 方法做相反的事情。这个 FlaskPassport 类还有一个用于检查权限的 View 装饰器方法。用于访问以序列化状态存储在 session 中的护照数据的代码看起来非常笨拙。更改后必须手动保存护照对象这一事实似乎不对 - 应该是 Flask 在自动处理请求后将更改后的护照对象保存到 session 中。

所以,我正在寻找一些聪明的模式,可以访问全局护照对象,所有 View 都可以访问,还可以让我向需要权限检查的 View 添加装饰器。

最佳答案

有多种方法可以做到这一点,包括:

  1. passport 实例存储在 g 上并使用 before_requestafter_request 处理程序对进行水化/将实例从/序列化到 session :

    @app.before_request
    def load_passport():
        if "passport_id" in session:
            g.passport = create_passport_from_id(session["passport_id"])
    
    @app.after_request
    def serialize_passport(response):
        if hasattr(g, "passport"):
            session["passport_id"] = g.passport.id
        return response
    
  2. 使用 Flask 用于 requestg(以及其他)的线程本地模式。在引擎盖下,这使用了 Werkzeug 的 LocalProxy,它安装在应用程序上下文或请求上下文上(取决于底层对象的生命周期):

    from flask import (_request_ctx_stack as request_ctx,
                       has_request_context, session)
    from werkzeug.local import LocalProxy
    
    current_passport = LocalProxy(get_passport)
    
    def get_passport():
        if has_request_context() and "passport_id" in session:
            if not hasattr(request_ct.top, "passport"):
                passport_id = session["passport_id"]
                request_ctx.top.passport = construct_passport_from_id(passport_id)
             return getattr(request_ctx.top, "passport", None)
        return EmptyPassport()
    
    @app.after_request
    def serialize(response):
        if current_passport.is_not_empty():
            session["passport_id"] = current_passport.id
        return response
    

值得注意的是,我选择不将整个护照序列化到 session 中,因为该信息会随着每个请求来回传递(取决于您在护照中存储了多少信息,这可能会也可能不会成为你关心的事情)。

同样值得注意的是,这两种方法都不是天生安全的。 Flask 确实签署了 session cookie 以使其防篡改,但您仍然需要担心注销、新鲜度等问题。看看 Flask-Login's code对于您需要考虑的其他一些事情。

关于python - 在 Flask 中建立持久化复杂对象的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24048778/

相关文章:

python - SQLAlchemy 和 Flask 的关系

javascript - Ajax post 返回 undefined

python - URL Builder TypeError error() 仅接受 1 个参数(给定 0 个)

python - 我可以在多进程中启动多线程 flask 吗

python - 为 python 3.5.2 安装 MySql

python - 使用 Dropbox 作为我的 Django 应用程序的服务器

python - 在 statsmodels 中自举混合效应回归系数

python - 索引以更快地搜索文件中的列表?

python - 如何获取 App Engine 实例的长格式 instance_id?

python - Flask Azure Web 应用程序部署成功但显示默认页面