Django的会话技术:Cookie、Session、Token、三者的区别

一.会话技术

1.介绍

  1. 请求过程Request开始,到Response结束
  2. 连接都是短连接
  3. 延长交互的生命周期
  4. 将关键数据记录下来
  5. Cookie是保存在浏览器端/客户端的状态管理技术
  6. Session是服务器端的状态管理技术
  7. Token是类似于自定义的session

2.详细过程

在浏览器中输入域名url,会经过dns服务器将域名解析成ip返回后,浏览器发送request对象请求给服务器,服务器收到请求后创建一个session对象,该对象会有个session_key的值,服务器会将该值以set_cookie消息头的形式发送给浏览器,浏览器接收到后,会将session_key的变量定义为session_id,session_id会存储在cookie中,当浏览器再次访问时,就会携带着session_id去服务器找对应的数据。
在这里插入图片描述

二.Cookie

1.Cookie介绍

Cookie是一种客户端会话技术,所有数据存储在客户端,其是以key-value进行数据存储层,服务器中是不做任何存储。
其特性:

  1. 支持过期时间
       max_age 毫秒
       expries 具体日期
  2. 根据域名进行cookie存储
  3. 不能跨网站(域名)
  4. 不能跨浏览器
  5. 自动携带本网站的所有cookie
  6. cookie默认不支持中文,base64

Cookie是服务器操作客户端的数据,通过Response进行操作。

2.Cookie基本使用

	设置cookie:response.set_cookie(key,value)
	获取cookie:username =request.COOKIES.get("username")
	删除cookie:response.delete_cookie("username")

登录案例:
(1)执行toCookieLogin跳转到cookieLogin的页面,在页面中输入名字,点击提交
(2)跳转到cookieWelcome页面,显示 欢迎xxx来到英雄联盟
(3)如果登录进入到了cookieWelcome的页面,在欢迎xxx来到英雄联盟的下面有一个退出,点击退出之后,显示欢迎游客来到英雄联盟。
创建主路由:

url(r'^cook/',include('CookieApp.urls')),

创建子路由:

url(r'^toCookieLogin/',views.toCookieLogin),

生成视图函数:

def toCookieLogin(request):
    return render(request,'cookieLogin.html')

创建cookieLogin.html模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>登录页面</h1>
</body>
</html>

运行结果:
在这里插入图片描述
编辑登录页面,为避免硬编码,使用反向解析:
修改主路由:

url(r'^cook/',include('CookieApp.urls',namespace='cook')),

创建子路由:

url(r'^cookieLogin/',views.cookieLogin,name='cookieLogin'),

添加表单:

<body>
    <h1>登录页面</h1>
    <form action="{% url 'cook:cookieLogin' %}" method="post">
        <input type="text" name="name">
        <button>登录</button>
    </form>

</body>

生成登录视图函数,并使用反向解析跳转到欢迎视图函数:

def cookieLogin(request):
    name = request.POST.get('name')
    response = redirect(reverse('cook:cookieWelcome'))
    response.set_cookie('name',name)
    return response

创建欢迎的视图函数,跳转到欢迎界面:

url(r'^cookieWelcome/',views.cookieWelcome,name='cookieWelcome'),
def cookieWelcome(request):

    name = request.COOKIES.get('name','游客')

    return render(request,'cookieWelcome.html',context=locals())

创建cookieWelcome.html模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>欢迎{{ name }}来到英雄联盟</p>
</body>
</html>

运行结果:
在这里插入图片描述

创建退出视图函数,以游客身份跳转到欢迎界面:

url(r'^cookieLogout/',views.cookieLogout,name='cookieLogout'),
def cookieLogout(request):

    response = redirect(reverse('cook:cookieWelcome'))
    response.delete_cookie('name')

    return response

cookWelcome.html模板修改:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>欢迎{{ name }}来到英雄联盟</p>
    <br>
    <a href="{% url 'cook:cookieLogout' %}">退出</a>
</body>
</html>

运行结果:
点击前:
在这里插入图片描述
点击后:
在这里插入图片描述

注意:
   1.出现403错误,可以在settings里注释掉: ‘django.middleware.csrf.CsrfViewMiddleware’,这一行,也可以在form表单中添加:{% csrf_token %}
  2.cookie默认不支持中文,输入中文不能正常跳转。

3.Cookie加盐

cookie数据保存在浏览器中,不安全:
在这里插入图片描述
所以我们可以对cookie进行加密,也就是俗称的cookie加盐

创建子路由:

url(r'^setCookieSalt/',views.setCookieSalt),
url(r'^getCookieSalt/',views.getCookieSalt,name='getCookieSalt'),

加密:
生成视图函数:

def setCookieSalt(request):
    response = redirect(reverse('cook:getCookieSalt'))

    response.set_signed_cookie('name','abc',salt='xxxxxxx')

    return response

解密:
生成视图函数:

def getCookieSalt(request):
    #获取的是加盐之后的数据
    name1 = request.COOKIES.get('name')
    print(name1)   #abc:1k0iSI:6tggbpd7vlIomnKt14hZ4NR-MIk
    #获取的是解密之后数据
    name = request.get_signed_cookie('name',salt='xxxxxxx')
    print(name)    #abc
    return HttpResponse('getCookieSalt')

运行结果:
在这里插入图片描述
在这里插入图片描述

salt是参数,其实加不加它,都一样。。。

4.Cookie过期时间

通过Response将cookie写到浏览器上,下一次访问,浏览器会根据不同的规则携带cookie过来
  max_age:整数,指定cookie过期时间 单位秒
  expries:整数,指定过期时间,还支持是一个datetime或 timedelta,可以指定一个具体日期时间
  max_age和expries两个选一个指定
  过期时间的几个关键时间
    max_age 设置为 0 浏览器关闭失效
    设置为None永不过期
    expires=timedelta(days=10) 10天后过期
案例:

def cookieLogin(request):
    name = request.POST.get('name')
    response = redirect(reverse('cook:cookieWelcome'))
    response.set_cookie('name',name,max_age=30)
    return response

上面设置了30秒cookie过期

三.Session

1.Session介绍

session是一种服务端会话技术,数据都存储在服务端,默认存在内存 RAM,在django被持久化到了数据库中,该表叫做Django_session,这个表中有三个字段,分别为seesion_key、session_data、expris_date。
Django中Session的默认过期时间是14天,支持过期,主键是字符串,默认做了数据安全,使用了BASE64
  - 使用的base64之后,那么这个字符串会在最后面添加一个==
  - 在前部添加了一个混淆串
session依赖于cookie

2.Session基本使用

设置session:   request.session["username"] = username
获取session:   username = request.session.get("username")
删除session:
                del request.session['username']
                    cookie是脏数据
                response.delete_cookie('sessionid')
                    session是脏数据
                request.session.flush()
		            冲刷,删除当前的会话数据并删除会话的cookie

登录案例,如cookie一样:
创建主路由:

url(r'^sess/',include('SessApp.urls')),

创建子路由:

url(r'^toSessionLogin/',views.toSessionLogin),

生成视图函数:

def toSessionLogin(request):
    return render(request,'SessionLogin.html')

创建SessionLogin.html模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>session登陆</h1>
</body>
</html>

运行结果:
在这里插入图片描述
编辑登录页面,为避免硬编码,使用反向解析:
修改主路由:

url(r'^sess/',include('SessApp.urls',namespace='sess')),

创建子路由:

url(r'^sessionLogin/',views.sessionLogin,name='sessionLogin'),

添加表单:

<body>
    <h1>session登陆</h1>
    <form action="{% url 'sess:sessionLogin' %}" method="post">
        <input type="text" name="name">
        <input type="submit" value="提交">
    </form>
</body>

生成登录视图函数,并使用反向解析跳转到欢迎视图函数:

def sessionLogin(request):
    name = request.POST.get('name')
    request.session['name'] = name
    return redirect(reverse('sess:sessionWelcome'))

创建欢迎的视图函数,跳转到欢迎界面:

url(r'^sessionWelcome/',views.sessionWelcome,name='sessionWelcome'),
def sessionWelcome(request):
    name = request.session.get('name','游客')
    return render(request,'sessionWelcome.html',context=locals())

创建sessionWelcome.html模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>欢迎{{ name }}来到英雄联盟</p>
</body>
</html>

运行结果:
在这里插入图片描述
创建退出视图函数,以游客身份跳转到欢迎界面:

url(r'^sessionLogout/',views.sessionLogout,name='sessionLogout'),
def sessionLogout(request):
    request.session.flush()
    return redirect(reverse('sess:sessionWelcome'))

sessionWelcome.html模板修改:

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>欢迎{{ name }}来到英雄联盟</p>
    <br>
    <a href="{% url 'sess:sessionLogout' %}">退出</a>
</body>
</html>

运行结果:
点击前:
在这里插入图片描述
点击后:
在这里插入图片描述

三.Token

1.token介绍

Token 的中文意思是“令牌”。其被认为是自定义的session又或者被认为是加密的唯一字符串,主要用来身份验证。 Facebook,Twitter,Google+,Github 等大型网站都在使用。比起传统的身份验证方法,Token 有扩展性强,安全性高的特点,非常适合用在 Web 应用或者移动应用上,如果使用在移动端或客户端开发中,通常以Json形式传输,服务端会话技术,自定义的Session,给他一个不能重复的字符串,数据存储在服务器中。

2.流程

使用基于 Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个Token,再把这个Token发送给客户端
  4. 客户端收到Token以后可以把它存储起来,比如放在 Cookie里或者Local Storage里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据

3.python常用Token生成方法

(1)binascii.b2a_base64(os.urandom(16))[:-1]
使用举例:

import binascii
import os
# os.urandom()返回一个二进制字节的值
print(os.urandom(16))

a = binascii.b2a_base64(os.urandom(16))[:-1]
print(a)

运行结果:

b'<\xce-\x85\xde\x19\x17=\x96D\x10\xa8H\x0f\r\xef'
b'BFXLsD5TMNVc/46wl2PDnA=='

总结:这种算法的优点是性能快, 缺点是有特殊字符, 需要加 replace 来做处理。

(2)sha1(os.urandom(16)).hexdigest()
使用举例:

import hashlib
import os

a = hashlib.sha1(os.urandom(16)).hexdigest()
print(a)

运行结果:

3014646c141cbff7fcf5d7eb2263f495fe709874

总结:这种算法的优点是安全,不需要做特殊处理。缺点是覆盖范围差一些。

(3)uuid4().hex
使用举例:

import uuid
a = uuid.uuid4().hex
print(a)

运行结果:

382ffb9b87ee4c1d91a5ae3ca6d94fa9

总结:Uuid使用起来比较方便, 缺点为安全性略差一些。

(4)base64.b32encode(os.urandom(20))/base64.b64encode(os.urandom(24))
使用举例:

import base64
import os
a = base64.b32encode(os.urandom(20))
print(a)

b = base64.b64encode(os.urandom(24))
print(b)

运行结果:

b'7KTWWTZMTL3I2D4H63MDCV4GHI6MMTR7'
b'+oHbnv5OOB6sRfOdOOrSNyNjvfXJnQLN'

总结:
  可以用base64的地方,选择binascii.b2a_base64是不错的选择
  根据W3的SessionID的字串中对identifier的定义,SessionID中使用的是base64,但在Cookie的值内使用需要注意“=”这个特殊字符的存在;
  如果要安全字符(字母数字),SHA1也是一个不错的选择,性能也不错;

4.Token应用

import time
import base64
import hmac


# 生产token
def generate_token(key, expire=3600):
    r'''''
        @Args:
            key: str (用户给定的key,需要用户保存以便之后验证token,每次产生token时的key 都可以是同一个key)
            expire: int(最大有效时间,单位为s)
        @Return:
            state: str
    '''
    ts_str = str(time.time() + expire)
    ts_byte = ts_str.encode("utf-8")

    sha1_tshexstr = hmac.new(key.encode("utf-8"), ts_byte, 'sha1').hexdigest()
    token = ts_str + ':' + sha1_tshexstr
    b64_token = base64.urlsafe_b64encode(token.encode("utf-8"))
    return b64_token.decode("utf-8")


# 验证token
def certify_token(key, token):
    token_str = base64.urlsafe_b64decode(token).decode('utf-8')
    token_list = token_str.split(':')
    if len(token_list) != 2:
        return False
    ts_str = token_list[0]
    if float(ts_str) < time.time():
        # token expired
        return False
    known_sha1_tsstr = token_list[1]
    sha1 = hmac.new(key.encode("utf-8"), ts_str.encode('utf-8'), 'sha1')
    calc_sha1_tsstr = sha1.hexdigest()
    if calc_sha1_tsstr != known_sha1_tsstr:
        # token certification failed
        return False
        # token certification success
    return True


key = "YFater"
print("key:", key)
user_token = generate_token(key=key)

print("加密后:", user_token)


user_de = certify_token(key=key, token=user_token)
print("验证结果:", user_de)
#
key = "yFater"
user_de = certify_token(key=key, token=user_token)
print("验证结果:", user_de)

运行结果:

key: YFater
加密后: MTU5NjAzMDcwNy42NzI2OTI4OmZkMWIxN2UzY2VmOGYxYTdjNDcxZTVmOGVhNmJlNWUyNzc2ZjY3NTQ=
验证结果: True
验证结果: False

四.三者区别

1.cookie与session的区别

(1)cookie数据存放在客户端上,session数据放在服务器上。
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE

2.session与token的区别

(1)作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击
(2)Session 是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 但是如果有了某个User的SID,就相当于拥有该User的全部权利.SID不应该共享给其他网站或第三方.
(3)Token,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App。其目的是让 某App有权利访问 某用户 的信息。这里的 Token是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值