一、Cookie
客户端技术,将数据信息存储到浏览器中,存储的结构是字典结构,即key-value.
Cookie是服务端创建,但保存于客户端,客户端每次发送请求时都会将Cookie信息发送到服务器(因为Cookie是请求头信息的一部分)
Cookie不支持中文,不能跨浏览器,不能跨域名
1、设置cookie
HttpResponse.set_cookie()
response.set_signed_cookie("Cookie名称","Cookie值",salt="盐")
属性:key
value
max-age 有效时长,单位为秒,指定为0,表示关闭浏览器失效(默认)指定为有效数值100表示100秒后自动失效,设置为None永不过期
expires 支持一个datetime或timedelta,可以指定一个具体的日期,expires=timedelta(days=10)表示十天后过期
max-age和xepires两个指定一个
# 普通设置,以明文的方式显示 def setcookie(request): response = HttpResponse('设置COOKIE成功') response.set_cookie('name','egon') return response
#加盐设置,以加密的形式显示 def do_login(request): uname = request.POST.get('uname') response = HttpResponseRedirect(reverse('app:mine')) # response.set_cookie('uname', uname, max_age=60) response.set_signed_cookie('content', uname, "Rock") return response
2、获取
HttpRequest.COOKIES.get(key)
request.get_signed_cookie("cookie名称",salt="盐")
def getcookie(request): return HttpResponse(request.COOKIES.get('name'))
def mine(request): # uname = request.COOKIES.get("content") try: uname = request.get_signed_cookie("content", salt="Rock") if uname: # return HttpResponse(uname) return render(request, 'mine.html', context={"uname": uname}) except Exception as e: print("获取失败") return redirect(reverse('app:login'))
3、删除
response.delete_cookie(key)
def logout(request): response = redirect(reverse("app:login")) response.delete_cookie("content") return response
二、Session
Session是用来表示一个用户与服务端的一次“会话”。使用客户端发送的sessionid(存在与Cookie中)与服务端的sessionid匹配,找到客户端请求所属的“会话”,经常用于登录验证。
Session一般保存在内存中,在Django中,Session默认使用数据库保存,若想变更Session的保存方式,需要添加SESSION_ENGINE配置信息,可以将session保存到redis中。
1、存储数据
HttpRequest.session[key] = value,数据进行了base64编码
2、读取数据
request.session.session_key 获取session_id
HttpRequest.session.get(key)
3、删除session
del request.session["key"]
request.session.flush() 同时清除cookie和session
request.session.clear() 清除所有session
def login(request): if request.method == "GET": return render(request, 'two_login.html') elif request.method == "POST": username = request.POST.get("username") request.session["username"] = username return HttpResponse("登录成功") def mine(request): username = request.session.get("username") print(request.session.session_key) return render(request, 'two_mine.html', context=locals()) def logout(request): response = redirect(reverse('myapp:mine')) # del request.session['username'] # response.delete_cookie('sessionid') # session cookie一起干掉 request.session.flush() return response
4、session重要配置
①、SESSION_EXPIRE_AT_BROWSER_CLOSE = True
当浏览器关闭时,清除本地Cookie
②、 SESSION_COOKIE_AGE = 60
设置session保存的秒数
5、扩展:将session保存到redis
①安装django-redis-sessions库
pip install django-redis-sessions
②在settings.py中配置
SESSION_ENGINE = 'redis_sessions.session' SESSION_REDIS = { 'host':'127.0.0.1', 'port':6379, 'db':0, 'password':'Redis密码', 'prefix':"key前缀", 'socket_timeout':5 }
三、Token
Token是为了弥补服务端会话技术的缺点(占用服务器资源)而产生的,Token验证的思想是“以时间换空间”.
当第一次验证成功(用户名和密码正确),服务端对用户数据进行签名生成一个token,并将该token发送到客户端,当客户端发送请求时,会携带该token到服务器端,服务端对该token进行解密验证,当验证成功,则说明用户验证通过,否则验证失败.
1、基本算法
①MD5摘要算法
用来验证数据完整性 ,单向不可逆,防爆破性高,统一输出,默认输出128位的二进制,32位的16进制使用hexdigest()
import hashlib md5 = hashlib.md5() md5.update('xxx'.encode()) crypto_str = md5.hexdigest()
②应用
基本时间+随机数生成MD5的32位字符串
import hashlib
import random
import time
m = hashlib.md5()
m.update(str(time.time()+ random.random()).encode())
a = m.hexdigest()
2、使用方式
①使用在移动端或客户端开发中,通常以Json形式传输,需要移动端自己存储Token,需要获取Token关联数据的时候,主动传递Token
def login(request): if request.method == "GET": return render(request, 'two_login.html') elif request.method == "POST": username = request.POST.get("username") m = hashlib.md5() m.update(str(time.time()+ random.random()).encode()) token = m.hexdigest() data = { 'status': 200, 'username': username, 'token': token # 设置token } return JsonResponse(data)
def mine(request): # 客户端访问时候需要带上token # http://127.0.0.1:8000/myapp/mine/?token=e912be747de3c51f11e9e9bea72b49bf
token = request.GET.get('token')
if token:
return JsonResponse({
'status': 'OK'
})
②在web开发中,Token和session类似,携带在cookie中。
def login(request): if request.method == 'GET': return render(request, 'login.html') else: name = request.POST.get('name') pwd = request.POST.get('pwd') users = User.objects.filter(name=name,pwd=pwd) if users: user = users.first() token = str(time.time()) user.token = token user.save() response = HttpResponse('<h3 style="color:green">登录成功</h3>') response.set_cookie('token',token) # 将token也保存于响应对象,发送给客户端 return response else: return HttpResponse('用户名或密码错误') def mine(request): token = request.COOKIES.get("token") if token: user = User.Objects.get(token=token) return HttpResponse('登录成功')
四、三者对比
Cookie使用更简洁,服务器压力更小,数据不是很安全
Session服务器要维护Session,相对安全
Token拥有Session的所有优点,自己维护略微麻烦,支持更多的终端