python - 如何在 Tornado RequestHandler 中存储数据库 session

标签 python session asynchronous sqlalchemy tornado

我正在 Tornado 中实现用于用户 session 管理的安全 cookie 方案。用户的详细信息通过 SQLAlchemy 访问。目前,我需要打开两个数据库 session :一个用于在身份验证期间验证用户是否存在,另一个用于查询模型的其他部分。像这样的事情:

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        user_id = self.get_secure_cookie('user')
        if not user_id:
            return None
        with model.session_scope() as session:
            user = session.query(model.AppUser).get(user_id)
            if not user:
                return None
            session.expunge(user)
        return user

class OtherHandler(BaseHandler):
    @tornado.web.authenticated
    @gen.coroutine
    def put(self, ob_id):
        with model.session_scope() as session:
             other = session.query(model.Other).get(ob_id)
             session.merge(self.current_user)
             if not user.can_view(other):
                 raise AuthzError
             yield self.some_operation(other)
        self.finish()

如果我不必使用 merge 将用户对象带回到 session 中,那就太好了。有没有一种安全的方法来存储数据库 session 和persistent处理程序中的 user 对象?我正在考虑做这样的事情:

class BaseHandler(tornado.web.RequestHandler):
    def prepare(self):
        self.session = model.Session()
        user_id = self.get_secure_cookie('user')
        if user_id:
            self.current_user = session.query(model.AppUser).get(user_id)

    def finish(self, chunk=None):
        try:
            return super().finish(chunk)
        finally:
            self.session.commit()

    def send_error(self, status_code=500, **kwargs):
        try:
            return super().send_error(status_code=status_code, **kwargs)
        finally:
            self.session.rollback()

问题:

  1. 即使使用异步代码(@gen .coroutineyield)?
  2. 我在 finishsend_error 中关闭 session 的方式稳健吗?我想确保没有任何僵尸 session 闲逛。

最佳答案

Is the way I'm closing the session in finish and send_error robust? I want to make sure I don't have any zombie sessions hanging around

您可以使用 on_finishon_connection_close .

def on_finish(self):
    if self.get_status_code() >= 500:
        self.session.rollback()
    else:
        self.session.commit()

请注意,可能存在更好的方法来区分错误响应。另请看一下讨论 - https://github.com/tornadoweb/tornado/issues/517

Is it safe to store the session (or anything else) in self, even when using async code (@gen.coroutine and yield)?

RequestHandler 对象是为每个请求创建的,它不是共享的。在这种情况下,异步不会使代码更容易受到攻击(我认为)将数据存储在“self”中。

关于python - 如何在 Tornado RequestHandler 中存储数据库 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45002671/

相关文章:

python - 如何将 Django 应用程序合并到现有的扭曲服务器中?

python - 有没有什么办法可以用扭曲的方式异步发布一些数据?

PHP 游戏 session 不工作

mysql - 交响乐2 : use MongoDB as session storage

php - Laravel 4 Redis session 连接

python - 是否可以将 Tornado 的 gen.engine 和 gen.Task 与扭曲一起使用?

python - 如何从列表 "Python": 打印字典

node.js - 在 Node/Express 的异步函数中捕获错误

用于异步消息传递的 Node.js REST API 包装器

python - 字符串化列表到两个单独的列表