RequestHandler 类的 get_current_user() 方法覆写无效

2015-07-27 23:43:49 +08:00
 roychan

刚刚开始用 Tornado。

在用户认证时,我覆写了 BaseHandler,以便使用内置的 current_user() 方法与 is_authenticated 修饰器。

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_secure_cookie('user')

在某步中,我加了判断 if self.current_user then xxx,此时即便登录了也无法执行 xxx,如果我把判断写成 if self.get_current_user then xxx,便能成功确认登录,xxx 就执行了。

请问这可能是什么问题?

4418 次点击
所在节点    Tornado
12 条回复
gx
2015-07-28 01:30:27 +08:00
`self.current_user`可以当作是`get_current_user`的一个缓存,如果你复写的`get_current_user`在第一次返回None的话,之后使用`self.current_user`是直接读取缓存的结果。

解决方案:
当你做登陆操作时,除了`set_secure_cookie`之外,可以给current_user赋值:
```
user = {'id': "v2ext208772", 'name': "roychan"}
self.current_user = user
```
roychan
2015-07-28 08:30:18 +08:00
@gx
那么是否退出的时候要再将这个值设置为 None?
这样是不是没有用到 Tornado 内置的 auth 功能了?
mulog
2015-07-28 08:52:17 +08:00
你可以看看你说的那两个东西的实现
https://github.com/tornadoweb/tornado/blob/master/tornado/web.py

如果你的 get_current_user() 真的就只是读 cookie 的话 我觉得这两的返回会是一致的呀
roychan
2015-07-28 09:06:03 +08:00
@mulog

正如一楼所说,get_current_user 方法在调用 current_user 方法时会被调用一次,然后将自身的 _current_user 属性设置为当前用户,以后直接调用自身属性,此为「缓存」。

假设:我现在要求访问登录页面也需要登录。那么在访问登录页面之前,需要调用一次 current_user 这个方法(也是属性)来验证是否登录。如果用户未登录,此时 current_user 值便成为了 None,即便登录后,使用 current_user 属性来验证的话,也依旧是 NoneType。

我想在不覆写 Tornado 源代码的情况下最大化实现其内置功能。如果还要自己加一个属性,那么我感觉设置安全 cookie 的验证步骤可以省去了(除了用来保持登录)。
roychan
2015-07-28 09:07:24 +08:00
@mulog

按照官方文档来看的话,只需要覆写 get_current_user 方法就可以了,不知道为什么不行。
siteshen
2015-07-28 09:30:48 +08:00
POST /login 后应该返回302,而不是继续停留在 /login 页面。
siteshen
2015-07-28 09:32:16 +08:00
@siteshen logout 同理,这样就能保证登录状态在整个请求中一致。
roychan
2015-07-28 09:41:55 +08:00
@siteshen 假设我手动访问登录页面呢?
mulog
2015-07-28 09:51:01 +08:00
@roychan
可是缓存也只是在同一个请求之内啊 你访问另一个页面/刷新之后哪来的缓存。。
roychan
2015-07-28 09:58:36 +08:00
那如何解决手动访问登录页的问题呢…
gx
2015-07-28 21:01:32 +08:00
@roychan 这个_current_user存在于内存当中,准确的说是在一个http_request生命周期内有效。

只要你重置了cookie,再次开始一个request都是current_user都是None;

一般情况下,登入和登出都会301/302,当然如果是单页面应用可以再次请求状态。
siteshen
2015-07-29 00:39:00 +08:00
@roychan 登录页面的作用仅仅是用于浏览器告诉服务器自己是谁,“已经登录”的意思是服务器知道你是谁了,登录过的用户服务器认为他应该到哪就返回 302 跳转到哪。

def login(request, next_url=None):
if self.current_user:
redirect(next_url or '/dashboard')

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/208772

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX