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登录

方法有三种:

  1. 删除客户端session_id
  2. 删除客户端session对话
  3. 两者都删除(最好)

方法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点击退出

我们发现第一行删除的干干净净。

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏