zoukankan      html  css  js  c++  java
  • tornado安全应用之用户认证

    在这个例子中,我们将只通过存储在安全cookie里的用户名标识一个人。当某人首次在某个浏览器(或cookie过期后)访问我们的页面时,我们展示一个登录表单页面。表单作为到LoginHandler路由的POST请求被提交。post方法的主体调用set_secure_cookie()来存储username请求参数中提交的值。

    代码如下:

    class BaseHandler(tornado.web.RequestHandler):

        def get_current_user(self):

            return self.get_secure_cookie("username")

    class LoginHandler(BaseHandler):

        def get(self, *args, **kwargs):

            self.render('login.html')

        def post(self, *args, **kwargs):

            self.set_secure_cookie("username",self.get_argument("username"))

    class WelcomeHandler(BaseHandler):

        @tornado.web.authenticated

        def get(self, *args, **kwargs):

            self.render('index.html',user=self.current_user)

    class LogoutHandler(BaseHandler):

        def get(self, *args, **kwargs):

            if (self.get_argument("logout",None)):

                self.clear_cookie("username")

                self.redirect('/')

    def server_function():

        cookie='bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E='

        tornado.options.parse_command_line()

        app = tornado.web.Application(handlers=[(r"/", WelcomeHandler),(r"/login",LoginHandler),(r"/logout",LogoutHandler)],template_path=os.path.join(os.path.dirname(__file__),"template"),

                                      static_path=os.path.join(os.path.dirname(__file__),"static"),ui_modules={'Book':HelloModule},cookie_secret=cookie,xsrf_cookies=True,login_url="/login")

        http_server = tornado.httpserver.HTTPServer(app)

        http_server.listen(options.port,address='127.0.0.1')

    tornado.ioloop.IOLoop.instance().start()

    首先来看下代码的运行原理:

    第一步:首先来看WelcomeHandler。这个类的get函数被@tornado.web.authenticated装饰器给装饰,我们进入这个装饰器的代码看下具体的实现:

    def authenticated(method):

        @functools.wraps(method)

        def wrapper(self, *args, **kwargs):

            if not self.current_user:

                if self.request.method in ("GET", "HEAD"):

                    url = self.get_login_url()

                    if "?" not in url:

                        if urlparse.urlsplit(url).scheme:

                            # if login url is absolute, make next absolute too

                            next_url = self.request.full_url()

                        else:

                            next_url = self.request.uri

                        url += "?" + urlencode(dict(next=next_url))

                    self.redirect(url)

                    return

                raise HTTPError(403)

            return method(self, *args, **kwargs)

        return wrapper

    第二步:authenticated首先判断self.current_user是否存在,self.crrent_user的值在tornado.web.RequestHandler中获得。这是一个RequestHandler的类属性。返回的是_current_user,而且_current_user 是通过self.get_current_user()获取的

        @property

        def current_user(self):

            if not hasattr(self, "_current_user"):

                self._current_user = self.get_current_user()

            return self._current_user

    而我们在BaseHandler中重写了get_current_user,从客户端发送的cookie中获取username的值。那么如果是第一次访问或者是cookie值失效后,得到的current_user将会是空

        def get_current_user(self):

            return self.get_secure_cookie("username")

    第三步:如果current_user为空,网页将重定向到login_url设置的页面连接。url = self.get_login_url()。在这个函数中通过return self.application.settings["login_url"]

    返回重定向的url

        def get_login_url(self):

            self.require_setting("login_url", "@tornado.web.authenticated")

            return self.application.settings["login_url"]

    第四步:进入登录界面的处理函数LoginHandler。在登录界面中将进行username的cookie值设置

    class LoginHandler(BaseHandler):

        def get(self, *args, **kwargs):

            self.render('login.html')

        def post(self, *args, **kwargs):

            self.set_secure_cookie("username",self.get_argument("username"))

    第五步:再次登录,由于current_user已经存在,因此跳转到index.html网页,并显示登录的用户名

    class WelcomeHandler(BaseHandler):

        @tornado.web.authenticated

        def get(self, *args, **kwargs):

            self.render('index.html',user=self.current_user

    代码已经解释完了,我们来看下具体的网页访问例子:

    第一步:浏览器中输入http://127.0.0.1:8003/,将会自动跳转到http://127.0.0.1:8003/login?next=%2F

    后台打印:

    [I 180105 10:11:05 web:2063] 302 GET / (127.0.0.1) 0.33ms

    [I 180105 10:11:05 web:2063] 200 GET /login?next=%2F (127.0.0.1) 0.68ms

    浏览器中查看cookie值,此时只有设置的_xsrf值

    第二步:此时在网页中输入用户名并点击login。再次查看cookie值,已经存在了username的cookie值

    第三步 再次登录http://127.0.0.1:8003/。可以看到没有跳转到登录界面,而是直接显示了登录用户。

    整个后台的打印:

    [I 180105 10:11:05 web:2063] 302 GET / (127.0.0.1) 0.33ms

    [I 180105 10:11:05 web:2063] 200 GET /login?next=%2F (127.0.0.1) 0.68ms

    [I 180105 10:14:50 web:2063] 200 POST /login (127.0.0.1) 1.46ms

    [I 180105 10:16:17 web:2063] 200 GET / (127.0.0.1) 0.64ms

  • 相关阅读:
    Android中实现ListView圆角效果[转]
    移动终端开发必备知识【转】
    android-supporting-multiple-devices
    Android @+id与@id的区别
    loading android
    Loading Image
    合理的薪酬策略——揭秘万达电商(3)
    Node.js的helloworld 程序
    codeforces Gravity Flip 题解
    HDU 3853 向下向右找出口问题-期望dp
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/8202809.html
Copyright © 2011-2022 走看看