美文网首页Python
Tornado-cookie和session

Tornado-cookie和session

作者: Python野路子 | 来源:发表于2018-07-14 11:31 被阅读0次

    cookie

    有什么办法能够让浏览器记住登录信息,下次再打开的时候可以自动登录?网站是如何记录登录信息的?

    设置cookie

            self.set_cookie('cookie_test','xiaobai') #默认过期时间是浏览器关闭会话时
    
    image.png
    self.set_cookie('cookie_test','xiaobai',expires=time.time() + 60) #设置过期时间为60秒
    
    image.png
    self.set_cookie('cookie_test','xiaobai',expires_days=1) #设置过期时间1天
    
    image.png
    self.set_cookie('cookie_test','xiaobai',path='/test') #设置路径,限定哪些内容需要发送cookie,/表示全部
    
    image.png
    image.png
    self.set_secure_cookie('cookie_test7','xiaobai') #设置一个加密的cookie,但是必须在下面的application里面添加cookie_secret = 'test',才可以
    
    ----
    self.set_secure_cookie('cookie_test7','xiaobai') #设置一个加密的cookie,但是必须在下面的application里面添加cookie_secret = 'test',才可以
    
    ----
    cookie_secret = 'test', #密码 通过这个将上面cookie内容进行加密
    
    image.png

    获取cookie

    get_cookie6 = self.get_cookie('cookie_test6') #获取一般的cookie
    get_cookie7 = self.get_secure_cookie('cookie_test7') #获取加密的cookie
    
    image.png

    整个代码示例:

    import tornado.httpserver
    import tornado.ioloop
    import tornado.options
    import tornado.web
    
    import util.ui_methods
    import util.ui_modules
    import time
    
    from tornado.options import define,options
    
    define('port', default= 8080, help='run port', type=int)
    
    class SetCookieHander(tornado.web.RequestHandler):
        def get(self):
            self.set_cookie('cookie_test1','xiaobai') #默认过期时间是浏览器关闭会话时
            self.set_cookie('cookie_test2','xiaobai',expires=time.time() + 60) #设置过期时间为60秒
            self.set_cookie('cookie_test3','xiaobai',expires_days=1) #设置过期时间1天
            self.set_cookie('cookie_test4','xiaobai',path='/test') #设置路径,限定哪些内容需要发送cookie,/表示全部
            self.set_cookie('cookie_test5','xiaobai',httponly=True) #设置js不能获取cookie
            self.set_cookie('cookie_test6','xiaobai',max_age=120,expires=time.time()+60) ##max_age优先级比expires高,前面为120s,所以根据前面的来
            self.set_secure_cookie('cookie_test7','jiami') #设置一个加密的cookie,但是必须在下面的application里面添加cookie_secret = 'test',才可以
    
            self.write('set cookie')
    
    
    class GetCookieHander(tornado.web.RequestHandler):
        def get(self):
            get_cookie6 = self.get_cookie('cookie_test6') #获取一般的cookie
            get_cookie7 = self.get_secure_cookie('cookie_test7') #获取加密的cookie
    
            print(get_cookie6,get_cookie7)
            self.write('get cookie')
    
    
    application = tornado.web.Application(
        handlers=[
            (r'/', SetCookieHander),
            (r'/get',GetCookieHander)
        ],
        template_path='templates',
        static_path='static',
        ui_methods=util.ui_methods,
        ui_modules=util.ui_modules,
        #也可以写成字典形式
        # ui_modules={'UiModule':util.ui_modules.UiModule},
        cookie_secret='test',  # 密码 通过这个将上面cookie内容进行加密
        debug=True
    )
    
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()
    

    登录验证

    当我们希望用户只需要在第一次登录的时候,输入账号和密码登录进去,之后就不用再输入用户名和密码就可以自动登录进去,也就是在第二次访问的时候,服务器是怎么能够自动识别用户信息的呢?

    1. 导入装饰器:
      from tornado.web import authenticated #导入装饰器
    2. 声明BaseHandler类:
    #设置BaseHandler类,重写函数get_current_user
    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self): #前面有绿色小圆圈带个o,再加一个箭头表示重写
            current_user = self.get_secure_cookie('ID')  #获取加密的cookie
            print(current_user)
            if current_user:
                return current_user
            return None
    
    1. 设置cookie:
    #在LoginHandler类中的post函数里面加上设置cookie
    class LoginHandler(tornado.web.RequestHandler):
        def get(self):
            self.render('login.html')
    
        def post(self,*args,**kwargs):
            user = self.get_argument('name','')
            username = User.by_name(user)
            passwd = self.get_argument('password','')
    
            if username and passwd == username[0].password:
                self.set_secure_cookie('ID', user)  # 设置加密cookie
                self.render('home.html',username=username)
            else:
                self.write('用户名或密码错误')
    
    1. 配置没有登录则跳转的路由:
      login_url='/login'
    application = tornado.web.Application(
        handlers = [
            (r'/login',LoginHandler),
            (r'/buy',BuyHandler),
        ],
        cookie_secret='1q2w3e4r',
        #设置跳转路由,为了防止在没有登录情况下,直接输入需要登录才可见的url进行访问,做判断,如果没有登录则跳转到这个路由下
        login_url='/login',
        template_path = 'templates', #想要Tornado能够正确的找到html文件,需要在 Application 中指定文件的位置
        debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
    )
    
    1. 装饰需要验证的请求:
    #在BuyHandler类里面添加装饰器,装饰需要验证的请求
    class BuyHandler(BaseHandler):
        @authenticated            #装饰器判断有没有登录,如果没有则跳转到配置的路由下去
        def get(self):
            self.write('buy')
    
    1. 如果之前没有登录,直接访问buy路径,则跳转到login去登录:
      image.png
      我们再来看看,跳转到登录界面输入用户名和密码登录之后,如何跳转到之前的页面(buy)呢?
      1.获取之前的路由,在使用 authenticated 之后,如果验证不成功,会自动跳转到登录路由,并且在 URL 后面加上 next 参数,next 参数的参数值就是之前的路由。
      image.png
        def get(self):
            nextname = self.get_argument('next','') #将原来的路由赋值给nextname
            self.render('login.html',nextname=nextname) #跳转页面带上获取的参数
    

    2.修改模板文件,在模板中添加next参数,并且值为之前的路由:

    <form method="post" action="/login?next={{nextname}}"> <!--在html模板中添加next参数,并且参数值为之前的路由-->
    

    3.修改post方法,获取之前的页面的路由,当登录验证通过之后,设置加密的 cookie ,并跳转到之前的路由。

    
        def post(self,*args,**kwargs):
            user = self.get_argument('name','')
            username = User.by_name(user)
            passwd = self.get_argument('password','')
    
            nextname = self.get_argument('next','') #获取之前页面的路由
    
            if username and passwd == username[0].password:
                self.set_secure_cookie('ID', user)  # 设置加密cookie
                self.redirect(nextname)     #跳转到之前的路由
            else:
                self.render('login.html',nextname=nextname)
    

    全部代码如下:

    #loginTest.py:
    import tornado.httpserver
    import tornado.ioloop
    import tornado.options
    import tornado.web
    from data.user_module import User
    from tornado.options import define,options
    
    from tornado.web import authenticated  #导入装饰器
    
    define('port', default=8080, help='run port', type=int)
    
    #设置BaseHandler类,重写函数get_current_user
    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self): #前面有绿色小圆圈带个o,再加一个箭头表示重写
            current_user = self.get_secure_cookie('ID')  #获取加密的cookie
            print(current_user)
            if current_user:
                return current_user
            return None
    
    #在LoginHandler类中的post函数里面加上设置cookie
    class LoginHandler(tornado.web.RequestHandler):
        def get(self):
            nextname = self.get_argument('next','') #将原来的路由赋值给nextname
            self.render('login.html',nextname=nextname) #跳转页面带上获取的参数
    
        def post(self,*args,**kwargs):
            user = self.get_argument('name','')
            username = User.by_name(user)
            passwd = self.get_argument('password','')
    
            nextname = self.get_argument('next','') #获取之前页面的路由
    
            if username and passwd == username[0].password:
                self.set_secure_cookie('ID', user)  # 设置加密cookie
                self.redirect(nextname)     #跳转到之前的路由
            else:
                self.render('login.html',nextname=nextname)
    
    
    
    #在BuyHandler类里面添加装饰器,装饰需要验证的请求
    class BuyHandler(BaseHandler):
        @authenticated            #装饰器判断有没有登录,如果没有则跳转到配置的路由下去
        def get(self):
            self.write('buy买买买!')
    
    application = tornado.web.Application(
        handlers = [
            (r'/login',LoginHandler),
            (r'/buy',BuyHandler),
        ],
        cookie_secret='1q2w3e4r',
        #设置跳转路由,为了防止在没有登录情况下,直接输入需要登录才可见的url进行访问,做判断,如果没有登录则跳转到这个路由下
        login_url='/login',
        template_path = 'templates', #想要Tornado能够正确的找到html文件,需要在 Application 中指定文件的位置
        debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
    )
    
    
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()
    
    #模板文件login.html:
    <body>
    <h1>登录</h1>
        <form method="post" action="/login?next={{nextname}}"> <!--在html模板中添加next参数,并且参数值为之前的路由-->
            用户名:<input type="text" name="name"/><br/>
            密 码:<input type="password" name="password"/><br/>
            <input type="submit" value="注册" />
        </form>
    
    </body>
    

    session

    可以用了解到 cookie 中的信息可以用来保存用户的登录信息,但是coolkie 是很容易被拦截的,所有其中必定不能有用户的任何私密信息,那么又有什么办法可以让服务器保存用户的登录信息,但是cookie中又不会有用户的任何信息呢?

    1. 安装对应模块
    pip install pycket 
    pip install redis
    
    1. 导入模块
    from pycket.session import SessionMixin
    
    1. 继承SessionMixin
    class BaseHandler(tornado.web.RequestHandler,SessionMixin):
    
    1. 添加配置:
    pycket = {
                'engine':'redis',
                'storage':{
                    'host':'localhost',
                    'port':6379,
                    'db_sessions':5,
                    'db_notifications':11,
                    'max_connections':2 ** 33,
                },
                'cookie':{
                    'expires_days':38,
                    'max_age':100
                }
            }
    
    1. 在BaseHandler里面修改设置cookie为设置session
    current_user = self.session.get('user') 
    
    1. 在LoginHandler里面的post里面修改获取cookie为获取session
    self.session.set('user', user)
    

    xsrf跨站伪造请求

    使用session可以保证用户信息不被cookie泄露,那如果攻击者不想获取用户信息,只是在提交form表单是攻击,该如何防范?
    只需要在html模板中添加

     {% module xsrf_form_html() %} 
    

    即可,当登录信息发送到服务器中去的时候,form表单和cookie里面都会有一个随机码,如果发送到服务器的时候这两个码不相同,那就表示被拦截了,服务器会拒绝客户端发送的请求。

    相关文章

      网友评论

        本文标题:Tornado-cookie和session

        本文链接:https://www.haomeiwen.com/subject/gqskpftx.html