V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Tornado Documentation
http://www.v2ex.com/tornado/
Tornado on GitHub
https://github.com/facebook/tornado/
Tornado Gists
http://tornadogists.org/
roychan
V2EX  ›  Tornado

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

  •  
  •   roychan · 2015-07-27 23:43:49 +08:00 · 4404 次点击
    这是一个创建于 3406 天前的主题,其中的信息可能已经有所发展或是发生改变。

    刚刚开始用 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 就执行了。

    请问这可能是什么问题?

    第 1 条附言  ·  2015-07-29 09:21:29 +08:00
    谢谢各位,问题解决了,下次我会多测试再来提问。
    12 条回复    2015-07-29 00:39:00 +08:00
    gx
        1
    gx  
       2015-07-28 01:30:27 +08:00   ❤️ 1
    `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
        2
    roychan  
    OP
       2015-07-28 08:30:18 +08:00   ❤️ 1
    @gx
    那么是否退出的时候要再将这个值设置为 None?
    这样是不是没有用到 Tornado 内置的 auth 功能了?
    mulog
        3
    mulog  
       2015-07-28 08:52:17 +08:00   ❤️ 1
    你可以看看你说的那两个东西的实现
    https://github.com/tornadoweb/tornado/blob/master/tornado/web.py

    如果你的 get_current_user() 真的就只是读 cookie 的话 我觉得这两的返回会是一致的呀
    roychan
        4
    roychan  
    OP
       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
        5
    roychan  
    OP
       2015-07-28 09:07:24 +08:00
    @mulog

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

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

    一般情况下,登入和登出都会301/302,当然如果是单页面应用可以再次请求状态。
    siteshen
        12
    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')
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2666 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:43 · PVG 19:43 · LAX 03:43 · JFK 06:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.