龙卷风中的曲奇和会话,tornado,cookie,session


使用的web框架:tornado

首先我们要了解为什么要用:cookie
百度百科是这样说的:

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 [1] 。

最关键的就是 进行辨别用户 ,因为http是无状态的,对于浏览器来说,每次HTTP请求都是一个新的请求。
1、无加密的cookie

只使用cookie进行用户的识别,也就是用过浏览器的cookie中保存一个值,请求的时候携带cookie,我们就可以从cookie中取出这个值,就可以判断谁是谁了。
tornado中设置
路由

(r"/login", Account.LoginHandle),

视图处理逻辑

class LoginHandle(tornado.web.RequestHandler):

    def get(self):
        username = self.get_cookie('user')
        if username:
            self.write('{}登录成功'.format(username))

        else:
            #进入else,说明没有进行登录,渲染登录页面到浏览器中
            self.render('account/login.html')

    def post(self):

        username = self.get_argument('username','')
        password = self.get_argument('password','')

        if username == 'root' and password == '123456':

            self.set_cookie('user',username)
            print(username)
            print(password)
            self.write({'errno':0,'errmsg':'登录成功'})

        else:
            #如果用户名和密码不对就重新重定向到登录路由中
            self.redirect('/login')

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
{#    {% module xsrf_form_html() %}#}

    username:<input id="username" type="text" name="username" /><br>

    password:<input id="password" type="password" name="password" /> <br>

    <input type="submit" value="登录" class="login-btn">

</form>
<script src="{{ static_url('js/admin/jquery.min.js') }}"></script>
{#<script src="{{ static_url('js/account/cookie.js') }}"></script>#}
{#<script src="{{ static_url('js/account/login.js') }}"></script>#}


</body>
</html>

当未登录时,返回login.html页面。
在这里插入图片描述
此时0个cookie。
在这里插入图片描述
输入账号密码进行登录:会进入当前路由的post请求中
在这里插入图片描述
登录成功返回数据:
在这里插入图片描述
可以通过浏览器查看到设置的cookie

在这里插入图片描述
当这时,在进行登录会看到返回root登录成功。
在这里插入图片描述

2、加密的cookie

就是对cookie的加密,使客户端看到是是一串加密后的cookie,虽然是加了密的但是还是把信息保存在了客户端。
因为是加密的所以我们要设置一个密钥;密钥可以自己随意设置。
也就是 'cookie_secret':'yoursecret', 这个字段

settings = {
    'debug':True,
    'template_path': os.path.join(os.path.dirname(
            os.path.dirname(__file__)), "templates"),
    'static_path':os.path.join(os.path.dirname(
            os.path.dirname(__file__)), "statics"),
    'static_url_prefix': '/statics/',
    'ui_methods':t_ui_methods,
    'cookie_secret':'yoursecret',
    #'login_url':'/admin/login',
    # 'xsrf_cookies':True,

}

视图处理逻辑,只是把get_cookie改为了get_secure_cookie,其它逻辑代码还是一样得 另外, html和路由也还是一样的

class LoginHandle(tornado.web.RequestHandler):

    def get(self):
        # username = self.get_cookie('user')
        username = self.get_secure_cookie('user')
        if username:
            self.write('{}登录成功'.format(username))

        else:
            #进入else,说明没有进行登录,渲染登录页面到浏览器中
            self.render('account/login.html')

    def post(self):

        username = self.get_argument('username','')
        password = self.get_argument('password','')

        if username == 'root' and password == '123456':

            # self.set_cookie('user',username)
            self.set_secure_cookie('user',username)
            print(username)
            print(password)
            self.write({'errno':0,'errmeg':'登录成功'})

        else:
            #如果用户名和密码不对就重新重定向到登录路由中
            self.redirect('/login')

可以先把刚才设置的无加密的cookie删除。
这是当我们请求登录页面时,可以就看到和刚才一样,我们未进行登录。
在这里插入图片描述
还是输入账号和密码
在这里插入图片描述
还是返回和登录成功的数据。
在这里插入图片描述
这是我们查看cookie中数据:看到内容时已经加密了。
在这里插入图片描述
只是在无加密的基础上加上密钥进行了加密。

3、session认证

第三种方式进行用户识别,这次我们不讲cookie的值保存在客户端了,我们把信息保存在服务端,这就用到了session,在客户端中我们只保留了一个session_id值,然后通过sessio_id再从后端取值,因此我们要用session保存的话,后端需要数据库进行保存信息。这里我们使用redis保存。注意:我们保存的是一个字典。

因为用到第三方包帮助我们进行session认证,
所以要安装

pip install pycket
pip install redis

设置:可以看到我们加上了pycket这个配置字段,用来连接redis。

settings = {
    'debug':True,
    'template_path': os.path.join(os.path.dirname(
            os.path.dirname(__file__)), "templates"),
    'static_path':os.path.join(os.path.dirname(
            os.path.dirname(__file__)), "statics"),
    'static_url_prefix': '/statics/',
    'ui_methods':t_ui_methods,
    'cookie_secret':'yoursecret',
    'pycket': {
         'engine': 'redis',
         'storage': {
             'host': '127.0.0.1',
             'port': 6379,
             'db_sessions': 10,
             'max_connections': 2 ** 31,
         },
         'cookies': {
             # 设置过期时间
             'expires_days': 2,
             #'expires':None, #秒
         },
     },
    # 'login_url':'/admin/login',
    # 'xsrf_cookies':True,

}

视图逻辑代码

from pycket.session import SessionMixin

#继承SessionMixin这个类,才能使用session
class LoginHandle(SessionMixin,tornado.web.RequestHandler):

    def get(self):
        # username = self.get_cookie('user')
        # username = self.get_secure_cookie('user')
        username = self.session.get('user')
        if username:
            self.write('{}登录成功'.format(username))

        else:
            #进入else,说明没有进行登录,渲染登录页面到浏览器中
            self.render('account/login.html')

    def post(self):

        username = self.get_argument('username','')
        password = self.get_argument('password','')

        if username == 'root' and password == '123456':

            # self.set_cookie('user',username)
            # self.set_secure_cookie('user',username)
            self.session.set('user',username)
            print(username)
            print(password)
            self.write({'errno':0,'errmeg':'登录成功'})

        else:
            #如果用户名和密码不对就重新重定向到登录路由中
            self.redirect('/login')

还是和刚才一样请求登录页面未进行登录。
在这里插入图片描述
输入账号密码:
在这里插入图片描述
登陆成功:
在这里插入图片描述
看到给我们的不是user了,而是一个id
在这里插入图片描述
当我们第一次请求的时候,就已经给我们设置了一个session_id
在这里插入图片描述
每次请求cookie中携带session_id值:
在这里插入图片描述
这时我们的redis数据库中就已经保存了这个值(字典):

进入数据库,因为我们选择的是10号数据库:
在这里插入图片描述
我们看到redis中有个进行了字典对象序列化的值;

我们进行反序列化:

import pickle

data = b'\x80\x03}q\x00X\x04\x00\x00\x00userq\x01X\x04\x00\x00\x00rootq\x02s.'

a = pickle.loads(data)

print(a)

我们就可以看到在数据库中保存的就是设置的session数据.
在这里插入图片描述