cookie与session
cookie与session
一、cookie与session简介
HTTP协议四大特性
1.基于请求响应
2.基于TCP、IP作用于应用层之上协议
3.无状态
服务端无法识别客户端的状态
1.互联网刚开始兴起的时候,所有人访问网址都是一样的数据
服务端无法识别客户端问题不大
2.互联网发展 淘宝、京东、阿里
服务端不得不想办法记住客户端的状态
cookie与session应运而生
4.无连接
我们都知道HTTP协议是无状态的,无状态的意思就是每次请求都是独立的,它的执行情况和结果与前面的请求和之后都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况;
'''人生只如初见''',对服务器来说,每次请求都是全新的;
状态可以理解为客户端和服务端在某次会话中产生的数据,那无状态的就以为这些数据不会被保留,会话中产生的数据又是我们需要保存的,也就是说要'保持状态',因此cookie就是在这样一个场景下诞生。
1.cookie
1.什么是cookie
保存在客户端上跟用户信息(状态)相关的数据
cookie具体指的是一段小信息,他是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息
2.cookie原理
由服务器产生内容,浏览器收到请求后保存在本地,当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是谁了
3.cookie主要用于以下三个方面
1.会话状态管理
2.个性化设置
3.浏览器行为跟踪
2.session
1.什么是session
保存在服务端上跟用户信息(状态)相关的数据
session代表着服务器和客户端一次会话的过程。session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的web页之间跳转,存储在session对象中的变量将不会丢失,而是在整个用户会话中一致存在下去,当客户端关闭会话,或者超时,session超时失效时会话结束。
2.cookie与session有什么不同
作用范围不同,Cookie保存在客户端(浏览器),Session保存在服务器端。
存取方式的不同,Cookie只能保存ASCII,Session可以存任意数据类型,一般情况下我们可以在Session中保持一些常用变量信息,比如说Userid等。
有效期不同,Cookie可设置为长时间保持,比如我们经常使用的默认登陆功能,Session一般失效时间较短,客户端关闭或者Session超时都会失效
隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。
session是基于cookie工作的(其实大部分的保存用户状态的操作都需要使用到cookie)
二、django操作cookie
虽然cookie是服务端告诉客户端浏览器需要保存内容
但是客户端浏览器可以选择拒绝保存,如果禁止了,那么只要需要记录用户状态的网站登陆功能都无法使用了!
如果想要让客户端浏览器保存cookie需要HttpResonse对象调用方法
直接返回 HttpResonse
return HttpResonse
间接返回 HttpResonse
return render()
return rediect()
return JsonResponse()
# 先用一个变量去接收HttpResponse()
obj = HttpResonse()
...(obj.操作cookie的方法)
return obj
设置cookie需要变形
obj = HttpResponse()
obj.操作cookie的方法
return obj
obj = render()
obj.操作cookie的方法
return obj
obj = redirect()
obj.操作cookie的方法
return obj
obj = JsonRepsonse()
obj.操作cookie的方法
return obj
登录操作
清楚数据
没有登录直接访问home页面
跳转到了登陆页面
from django.shortcuts import render, HttpResponse,redirect
# Create your views here.
def set_cookie(request):
obj = HttpResponse('迟到的深情比草贱!')
# 让浏览器保存cookie数据,是以键值对的形式存储的
obj.set_cookie('name', 'jason')
return obj
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
obj = HttpResponse('登录成功')
obj.set_cookie('name', 'jasonNB')
return obj
return render(request, 'login.html')
return render(request, 'login.html')
def home(request):
if request.COOKIES.get('name'):
return HttpResponse('home 页面 只有登录的用户才可以查看')
return redirect('/login/')
def index(request):
if request.COOKIES.get('name'):
return HttpResponse('index页面 只有登录的用户才可以查看')
return redirect('/login/')
多个视图函数都需要校验用户是否登录,使用装饰器
加了装饰器以后就不会因为美加一个装饰器都会要去在视图函数里面写登录验证的代码,统一交给了装饰器
from django.shortcuts import render, HttpResponse,redirect
# 校验用户是否登陆的装饰器
def login_auth(func):
def inner(request, *args, **kwargs):
# print(request.path_info)
# print(request.get_full_path()) # 两种方法能够获取到用户上一次想要访问的url
# 获取用户上一次想访问的url
target_url = request.get_full_path()
# 获取cookie
if request.COOKIES.get('username'):
return func(request, *args, **kwargs)
else:
# 在用户没有登陆的情况 携带用户想访问的url参数
return redirect('/login/?next=%s' % target_url)
return inner
# 登陆功能
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
# 获取用户上一次想要访问的url
target_url = request.GET.get('next') # 这个结果可能是None
if target_url:
# 保存用户登陆状态
obj = redirect(target_url)
else:
# 保存用户登陆状态
obj = redirect('/home/')
# 2.让浏览器记录cookie数据 设置cookie
obj.set_cookie('username','jason666') # 告诉浏览器存一个k:v键值对
"""
1.浏览器不单单会帮你存
2.而且后面每次访问你的时候还会带着它过来
"""
# 跳转到一个需要用户登陆之后才能看的页面
return obj
return render(request, 'login.html')
@login_auth
def home(request):
# # 1.获取cookie信息 判断有没有登陆
# if request.COOKIES.get('username') == 'jason666':
# return HttpResponse('home主页,登陆成功之后才能进入')
# # 2.没有登陆应该跳转到登陆页面
# return redirect('/login/')
# 装饰器代表以上nobility方式
return HttpResponse('home主页,登陆成功之后才能进入')
@login_auth
def index(request):
return HttpResponse('index页面,登陆成功之后才能进入')
@login_auth
def func(request):
return HttpResponse('func页面,登陆成功之后才能进入')
如何记住用户登录之前想要访问的页面 用户登录成功之后自动跳转
可以拿到用户想访问的后缀,那么问题又来了,如果用户像访问一个没有登录的页面,那么它先走哪一步呢>>>登录装饰器,那么就可以在登录装饰器上操作数据
def login_auth(func_name):
def inner(request, *args, **kwargs):
if request.COOKIES.get('name'):
res = func_name(request, *args, **kwargs)
return res
else:
target_path = request.path_info
return redirect(f'/login/?next={target_path}') # ?后面的不参与路由匹配
return inner
如果是login页面那么后面就不会带参数了
场景1:用户访问了其他需要登录才可以访问的页面 如何跳转>>>:想要访问的
在装饰器login_auth内设置一个获取用户上一次想访问的url,将用户想访问的url放在当作参数get请求重定向发送给login,login获取用户想访问的url,然后判断生成对象,重定向返回
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
target_path = request.GET.get('next')
if target_path:
obj = redirect(target_path) # 如果有值则跳转到指定页面
else:
obj = redirect('/home/') # 如果没有值则跳转到首页
obj.set_cookie('name', 'jasonNB')
return obj
return render(request, 'login.html')
场景2:用户直接访问的登录页面 如何跳转>>>:网址首页
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
target_path = request.GET.get('next')
if target_path:
obj = redirect(target_path) # 如果有值则跳转到指定页面
else:
obj = redirect('/home/') # 如果没有值则跳转到首页
obj.set_cookie('name', 'jasonNB', max_age=3)
return obj
return render(request, 'login.html')
设置过期时间
例如:如果我们登录了一个网站长时间没有浏览,那么过一段时间它就会要求重新登录
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
target_path = request.GET.get('next')
if target_path:
obj = redirect(target_path) # 如果有值则跳转到指定页面
else:
obj = redirect('/home/') # 如果没有值则跳转到首页
obj.set_cookie('name', 'jasonNB', max_age=3) # 设置3秒,3秒过后就会登录失效
return obj
return render(request, 'login.html')
注销功能
注销之后,就已经清除Cookie,就不能再访问home了
# 只有登陆的用户才能注销
@login_auth
def logout(request):
# 返回主页
obj = redirect('/login/')
# 删除指定的键值对
obj.delete_cookie('username')
return obj
三、django操作session
session的工作机制
当客户端登录成功之后,然后服务端会产生一个随机字符串返回给客户端保存,并且服务端争对这些随机字符串会对用户数据做对应关系,然后做一个保存,将这些数据保存到服务端,然后存到表中,这里报这个错误是因为django在执行数据库迁移命令的时候,会自动创建好多好多张不是我们添加进去的表,这些表中就有django_session表,这张表就是专门用来存储session相关服务端的数据,因此想要执行session,必须先执行迁移命令
1.django默认的session失效时间14天
2.客户端会接收到键值对 键默认是sessionid值是加密的随机字符串(令牌)
执行迁移命令以后,就可以访问到了
request.session['name'] = 'jason'
1.django自动产生一个随机字符串返回给客户端(对name加密)
2.往django_session创建数据(对jason加密)
def set_session(request):
request.session['name'] = 'jason'
return HttpResponse('设置session')
request.session.get('name')
1.自动从请求中回去sessionid对应的随机字符串
2.拿着随机字符串去django_session中匹配数据
3.如果匹配上还会自动解密数据并展示
def get_session(request):
print(request.session.get('name'))
return HttpResponse('获取session')