Session的由来
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。
我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
Session流程解析
存Session:
1、在服务端生成随机字符串
2、生成一个和上面随机字符串对应的大字典,用来保存用户的数据
3、随机字符串当成cookie返回给浏览器
取Session
1、从请求携带的cookie里面找到随机的字符串
2、拿到随机的字符串去sission中找对应的大字典
3、从大字典中根椐key取值
所以Session必须依赖于Cookie
获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']
request.session.flush()
综合案例:
- 装饰器
def login_check(fn):
def innr(request, *args, **kwargs):
# ret = request.get_signed_cookie('loging', default='0', salt='adoef')
ret = request.session.get('loging')
if ret == '123':
return fn(request, *args, **kwargs)
else:
next_url = request.path_info
return redirect('/login/?next={}'.format(next_url))
return innr
- login.py
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('psd')
next_url = request.GET.get('next')
if username == "abc" and password == "123456":
if next_url:
rep = redirect(next_url)
else:
rep = redirect('/home/')
request.session['loging'] = '123'
# rep.set_signed_cookie('loging', '123', salt="adoef")
return rep
return render(request, 'login.html')
- 被装饰的
@login_check
def student(request):
return render(request, 'student.html')
@login_check
def home(request):
return render(request, 'home.html')
- 注销
def loginout(request):
request.session.flush()
return redirect('/login/')
输入http://127.0.0.1:8000/login/,登录成功后跳转到http://127.0.0.1:8000/home/,网页查找session对应的是服务端MySQL数据库session表中对应的字符串,浏览器根椐字符串找到服务端上的大字典并取出KEY值
因为还是在session有效状态,所以输入http://127.0.0.1:8000/student/返回的仍有session表中对应的字符串。
在home页面我们点击注销返回login页面
session状态已被清除
与上章一样,我们输入http://127.0.0.1:8000/student/,直接跳转到
http://127.0.0.1:8000/login/?next=/student/