zoukankan      html  css  js  c++  java
  • Tornado-Lesson09-cookie登录验证-session和XSRF

    一、cookie

      1.cookie的概念

        指服务器为了识别用户身份,缓存在浏览器本地的数据;多用于保存登录状态

      2.cookie的使用

        1)设置cookie

          set_cookie(name, value)

          set_cookie(name, value, expires = time.time()+n)  设置过期时间为n秒

          set_cookie(name, value, expires_days = n)  设置有效期,n天

          set_cookie(name, value, max_age = n, expires = time.time()+n)  max_age;min_age限制有效期最大和最小时间

          set_cookie(name, value, path = '/’)  设置路径

          set_cookie(name, value, httponly = True)  设置httponly = True,该cookie无法被js获取

          self.set_secure_cookie(name, value)  设置一个加密的cookie,需要在application中设置cookie_secret

          self.clear_cookie(name)  删除cookie,调用可以看到cookis信息为空

          self.clear_all_cookies()   删除此请求发送的全部cookie

          注:set_cookie中value不能包含空格,否则报错

        2)获取cookie

          self.get_cookie(name)

          self.get_secure_cookie(value) 

          注:get_secure_cookie获取的cookie是bytes类型,get_cookie获取的是str类型


    二、登录验证

      1.利用cookie登录验证

        1)导入装饰器

          from tornado.web import authenticated

        2)声明BaseHandler

          class BaseHandler(tornado.web.RequestHandler):

            def get_current_user(self):

              current_user = self.get_secure_cookie('cookie_name')

              if current_user:

                return current_user

              return None

        3)配置路由

          在applaction中添加 login_url = '/login'

        4)调用装饰器验证请求

          继承BaseHandler,并使用装饰器@authenticated

          class BuyHandler(BaseHandler):

            @authenticated

            def get(self):

              self.write('BuyHandler')

         这样,当路由跳转BuyHandler时候,先判断有没有cookie,如果有,则正常显示页面。如果没有cookie信息,则跳转到login_url所配置的路由

     

      2.从某一路由跳转到登录页面的完整cookis验证流程

        cookie_test.py

    import tornado.ioloop
    import tornado.web
    import tornado.httpserver
    import tornado.options
    import json
    import time
    import util.ui_methods
    import util.ui_modules
    
    from tornado.options import define, options
    
    from data.user_module import User
    
    from tornado.web import authenticated
    
    import data
    
    print(dir(data))
    print(data.name)
    
    define('port', default=8080, help='run port', type=int)
    define('version', default='0.01', help='version', type=str)
    
    
    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self):
            current_user = self.get_secure_cookie('ID')
            if current_user:
                return current_user
            return None
    
    
    class SetCookieHandler(tornado.web.RequestHandler):
        def get(self, *args, **kwargs):
            self.set_cookie('cookie_test', 'this_is_cookie_test')
            self.set_cookie('cookie_test_1', 'this_is_cookie_test_1', expires_days=1)  #设置有效期,生成时间+n秒
            self.set_cookie('cookie_test_2', 'this_is_cookie_test_2', expires_days=1)   #设置有效期1天
            self.set_cookie('cookie_test_3', 'this_is_cookie_test_3', expires_days=1, path='/test/')  # 设置有路径
            self.set_cookie('cookie_test_4', 'this_is_cookie_test_4', expires_days=1, httponly=True)  # js不可获取
            self.set_cookie('cookie_test_5', 'this_is_cookie_test_5', max_age= 120, expires=time.time() + 180) #限制最大时间
            self.set_cookie('cookie_test_6', 'this_is_cookie_test_6', max_age=120, expires=time.time() + 60)  # 限制最大时间
            self.set_secure_cookie('cookie_test_7', 'this_is_cookie_test_7')
            # self.clear_cookie('cookie_test')
            # self.clear_all_cookies()
    
    
    class GetCookieHandler(tornado.web.RequestHandler):
        def get(self):
            get_cookie1 = self.get_cookie('cookie_test_1')
            get_cookie2 = self.get_cookie('cookie_test_2')
            get_cookie3 = self.get_secure_cookie('cookie_test_7')
            print(type(get_cookie1))
            print(type(get_cookie2))
            print(type(get_cookie3))
            self.write(get_cookie1 + '<br>' + get_cookie2 + '<br>' + str(get_cookie3, encoding = "utf-8"))
    
    
    class LoginHandler(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
            nextname = self.get_argument('next', '')
            self.render('login.html', nextname=nextname, error = None)
    
    
        def post(self, *args, **kwargs):
            nextname = self.get_argument('next', '')
            user = self.get_argument('name', '')
            username = User.by_name(user)
            password = self.get_argument('password', '')
            if username and password==username.password:
                self.set_secure_cookie('ID', username.username)
                # self.render('login_success.html',
                #             username = username.username
                #             )
                self.redirect(nextname)
            else:
                self.render('login.html', nextname=nextname, error = '用户名和密码错误')
    
    class BuyHandler(BaseHandler):
        @authenticated
        def get(self, *args, **kwargs):
            self.write('这个问题冲钱就能解决')
    
    application = tornado.web.Application(
        handlers=[
        (r"/login", LoginHandler),
        (r"/buy", BuyHandler),
        (r"/set", SetCookieHandler),
        (r"/get", GetCookieHandler)
        ],
        debug=True,
        static_path = 'static',
        template_path = 'templates',
        ui_methods=util.ui_methods,
        # ui_modules=util.ui_modules,
        cookie_secret = 'abcdefg',
        login_url = '/login',
        ui_modules={'UiModule':util.ui_modules.UiModule}
    )
    
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        print(options.port)
        print(options.version)
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()

      login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Tornado</title>
    </head>
    <body>
    {% if error %}
        用户名或密码错误
    {% else %}
        Welcome!
    {% end %}
    <form method="post" action="/login?next={{ nextname }}">
        <p>用户名<br><input type="text" name="name"></p>
        <p>密码<br><input type="password" name="password"></p>
        <input type="submit">
    </form>
    
    
    </body>
    </html>
    

        看上面代码,当输入网址,跳转到/buy路由时,BuyHandler继承了BaseHandler并使用了装饰器@authenticated,由以下该源码装饰器可以看出,该装饰器作用是判断是否有cookie;

        如果有,则正常返回get请求。

        如果没有则返回applaction中login_url配置的路由,并在后面加上"?next=next_url",next_url就是之前跳转过来的路由"/buy".

    def authenticated(method):
        """Decorate methods with this to require that the user be logged in.
    
        If the user is not logged in, they will be redirected to the configured
        `login url <RequestHandler.get_login_url>`.
    
        If you configure a login url with a query parameter, Tornado will
        assume you know what you're doing and use it as-is.  If not, it
        will add a `next` parameter so the login page knows where to send
        you once you're logged in.
        """
        @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
    

        当没有cookie时候的运行结果:

                      

        当有cookie,正常跳转到写入数据

    三、登录验证

    四、XSRF

     

     

     

     

     

  • 相关阅读:
    mysql主从复制+读写分离
    lnmp平台菜鸟入门级笔记
    Shell编程
    Shell编程之--“grep-awk-sed” 基础用法汇总
    Nginx
    LB负载均衡之Nginx-Proxy
    LB(Load balance)负载均衡集群-LVS
    HA(High available)-Keepalived高可用性集群(双机热备)单点实验
    HA(High available)--Heartbeat高可用性集群(双机热备)
    linux -小记(3) 问题:linux 安装epel扩展源报错
  • 原文地址:https://www.cnblogs.com/bear905695019/p/8598777.html
Copyright © 2011-2022 走看看