[英]How to store database session in Tornado RequestHandler
I'm implementing a secure cookie scheme for user session management in Tornado. 我正在Tornado中实现用于用户会话管理的安全cookie方案。 The user's details are accessed via SQLAlchemy.
用户的详细信息可通过SQLAlchemy访问。 Currently I need to open two database sessions: one to verify that a user exists during authentication, and another to query other parts of the model.
当前,我需要打开两个数据库会话:一个用于验证用户在身份验证期间是否存在,另一个用于查询模型的其他部分。 Something like this:
像这样:
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()
It would be nice if I didn't have to use merge
to bring the user object back into the session. 如果我不必使用
merge
将用户对象带回到会话中,那就太好了。 Is there a safe way to store the database session and persistent user
object in the handler? 有没有安全的方法将数据库会话和持久性
user
对象存储在处理程序中? I'm considering doing something like this: 我正在考虑做这样的事情:
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()
Questions: 问题:
session
(or anything else) in self
, even when using async code ( @gen.coroutine
and yield
)? session
(或其他任何东西)在self
使用异步代码(时,即使@gen.coroutine
和yield
)? finish
and send_error
robust ? finish
和send_error
关闭会话的方式是否可靠 ? I want to make sure I don't have any zombie sessions hanging around. Is the way I'm closing the session in finish and send_error robust?
我在finish和send_error中关闭会话的方式是否可靠? I want to make sure I don't have any zombie sessions hanging around
我想确保我没有任何僵尸会议
You can use either on_finish
or on_connection_close
. 您可以使用
on_finish
或on_connection_close
。
def on_finish(self):
if self.get_status_code() >= 500:
self.session.rollback()
else:
self.session.commit()
Note that may exist a better way to distinguish an error response. 请注意,可能存在区分错误响应的更好方法。 Also take a look at the discussion - https://github.com/tornadoweb/tornado/issues/517
还可以看看讨论-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)?
即使使用异步代码(@ gen.coroutine和yield),将会话(或其他任何内容)自身存储起来是否安全?
The RequestHandler
object is created for every request, it's not shared. 为每个请求创建
RequestHandler
对象,但不共享该对象。 Asynchronous in that context, does not make the code more vulnerable (I think) to store data in " self
". 在这种情况下,异步不会使代码更容易(我认为)将数据存储在“
self
”中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.