Session
- 服务端会话技术
- 数据存储在服务器中
- 默认Session存储在内存中
- Django中默认会把Session持久化到数据库中,这样才能共享数据
- Django中Session的默认过期时间是14天
- 主键是字符串
- 数据是使用了数据安全
- 使用的base64
- 在前部添加了一个混淆串
- Session依赖于Cookie
服务器端会话技术,依赖于cookie
django中启用SESSION
在settings中
INSTALLED_APPS:
'django.contrib.sessions'
MIDDLEWARE:
'django.contrib.sessions.middleware.SessionMiddleware'
将内存中的数据保存到数据库中,是有django中的session模块帮助实现的。
每个HttpRequest对象都有一个session属性,也是一个类字典对象
常用操作
- get(key,default=None) 根据键获取会话的值
- clear() 清楚所有会话
- flush() 删除当前的会话数据并删除会话的cookie
- delete request['session_id'] 删除会话
- session.session_key获取session的key
设置数据
- request.session[‘user’] = username
- 数据存储到数据库中会进行编码使用的是Base64
实践:Session登录
新建two项目
url:
url('login/', views.login, name='login')
views:
# 将原本的login,do_login和在一起
def login(request):
# 这里的get指的是客户端从服务器获取信息,即访问该网址
if request.method == 'GET':
return render(request, 'two_login.html')
# post指的是客户端发送参数数据给服务器
elif request.method == 'POST':
username = request.POST.get('username')
# 服务器将获取到的username,存在session当中
request.session['username'] = username
return HttpResponse('登录成功')
Django 中post与get区别,https://www.cnblogs.com/zhansheng/p/11823689.html
优秀程序
松耦合
- 解耦合
- 高内聚,一个功能一块搞定,不能散开到很多地方
- 可扩展性
- 可延伸
接着我们写一个url用来做登陆中心的路由:
url('^mine/', views.mine, name='mine'),
views:
def mine(request):
username = request.session.get('username')
return HttpResponse(username)
我们访问two/login
点击登录,接着手动转到mine
接着我们查看数据库中的django_session表
我们再查看这张表的DDL
session_data是通过加密且以等号结尾的,只要加密以等号结尾的就考虑是base64加密的
密文:YjhhN2EyZWI0YTBmNThmMzE5YzE4ZmMyN2UxNjFjYWZhNTIyMzIyNTp7InVzZXJuYW1lIjoiXHU4MDAxXHU5NGMxXHU1M2NjXHU1MWZiNjY2In0=
我们将session_data中的密文进行解码:
b8a7a2eb4a0f58f319c18fc27e161cafa5223225:{"username":"\u8001\u94c1\u53cc\u51fb666"}
会发现之前的:老铁双击666 这个公户名被转化成了\u开头的编码,这个编码是unicode编码,因为不支持中文,所以转成了其他形式
而且在前部还添加了一个混淆串
这说明了我们再网站提交中文时服务器转换成其他形式存储,当我们要获取刚刚提交的中文时,服务器再转换回来。
cookie是服务器发放给客户端令牌,客户端拿着令牌访问,就知道了你是你
而session依赖于cookie
**
我们可以看到,session对话中也携带cookie,而且有sessionid,sessionid正好对应的是数据库中django_seeion的seeion_key主键,服务器根据客户端的cookie中的sessionid,和自己数据库中的key进行匹配,这样就识别了你是你。
同样删除了cookie,session也会失效,而且服务器数据库中的对应的session记录就成了辣鸡数据。
总结
session是服务端会话技术,数据存储在服务端,当我们调用request.session['名字'] 然后给他传递值的时候,在赋值的时候要存储这个session,存储时同时也会将session存到django_session的表中,表中会生成一个session_key主键,之后数据存在session_data内,默认还会设置一个过期时间。客户端怎么在下次访问时还能找到服务端保存的session?是这样的,服务端会通过cookie返回一个唯一标识session_key传给客户端保存,客户端将session_key起了一个新的名字叫做session_id将session_key的值存在了session_id里面,以后客户端访问客户端,带着session_id
根据session_key找到数据库中匹配的行,然后取出session_data中的存储数据。
流程图
实践:退出session登录
方法有三种:
- 删除客户端session_id
- 删除客户端session对话
- 两者都删除(最好)
方法1:仅删除客户端session_id
新建two_mine.html页面用来当作个人中心
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>mine</title>
</head>
<body>
<h2>欢迎回来{{ username }}</h2>
<a href="{% url 'two:logout' %}">退出</a>
</body>
</html>
新建url
url('^logout', views.logout, name='logout'),
views:
def logout(request):
response = redirect(reverse('two:mine'))
# 删除cookie
response.delete_cookie('sessionid')
return response
可以看到我们退出之后返回了,NONE
方法2:仅删除服务端session
直接用delete删除:
def logout(request):
response = redirect(reverse('two:mine'))
# 删除服务端session
del request.session['username']
# 删除客户端cookie
# response.delete_cookie('sessionid')
return response
以上两种方法都有缺陷:
方法1因为只删除了客户端的sessionid,而服务端session没有删除,导致产生大量辣鸡数据
方法2看似服务端删除了,实际上:
我们只删除了数据库中django_session表中的session_data内的数据,而key并没有删除,我们可以看到已经删除后的session_data的密文长度已经变短,因为删除了很多的东西,所以服务端删除session只是部分删除,仍有辣鸡数据。
方法3:客户端cookie,服务端session一起删
views:
def logout(request):
response = redirect(reverse('two:mine'))
# session,cookie一起删
request.session.flush()
return response
然后点击登录。
我们可以看到第一行数据
这时我们访问Mine点击退出
我们发现第一行删除的干干净净。
此处评论已关闭