【Django 013】Django2.2会话技术之Session

上一篇《【Django 012】Django2.2会话技术详解之cookie》中我们一起看了会话技术的第一种:cookie。今天来看第二种:session。因为session是基于cookie的,所以没有cookie基础的朋友们建议先看一下上一篇文章。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

操作环境

先总结下我的操作环境:

  • Centos 7
  • Python 3.7
  • Pycharm 2019.3
  • Django 2.2

因为Django长期支持版本2.2LTS和前一个长期支持版本1.11LTS有许多地方不一样,需要小心区分。

Session vs Cookie

上一篇讲到会话技术一共有三种,分别是

  • Cookie
  • Session
  • Token

Cookie是一种客户端会话技术,数据以键值对存储在客户端。支持过期时间,只针对本网站,不能跨网站或者跨域名。服务端通过HttpResponse发送给客户端。

而作为对比,Session是一种服务端会话技术,数据存储在服务器中。默认情况下Session存储在内存中,但是Django会将其持久化到数据库中。

数据库存储

完成默认迁移之后,可以看到有一张django_session表,包含三个字段,其DDL如下

create table django_session
(
    session_key  varchar(40) not null
        primary key,
    session_data longtext    not null,
    expire_date  datetime(6) not null
);

create index django_session_expire_date_a5c62663
    on django_session (expire_date);

session的信息就存在这张表当中,下面会用实例来看看这三个字段的作用。

session实现简单登录场景

这里还是实现cookie那一篇完成的一个简单登录交互

  1. 用户访问/login/页面填写一个只包含用户名的登录表单
  2. 表单中的提交按钮向后端的API提交用户名,并记录session
  3. 服务器自动跳转到用户个人主页/homepage/,显示用户已成功登录
  4. Session没过期的情况下用户可直接进入个人主页,不然自动跳转到登陆页面
  5. 在个人主页可以注销账号退出

新建一个叫sess的应用来完成这次功能,在settings.py中注册这个应用并且在urls.py中包含应用级别的路由规则。然后就可以开始下面的操作了。

在上一篇cookie中,我们用了4个路由完成的这一交互,分别是

  • login - 登录页面展示和表单提交
  • dologin - 表单提交的API
  • homepage - 主页展示
  • logout - 退出API

这里我们将login和dologin合并为单个路由,使得代码更加精简。

创建和获取session

创建两个路由如下

path('login/',views.login, name='login'),
path('homepage/',views.homepage, name='homepage'),

注意这里创建的login函数

def login(request):
    if request.method == 'GET':
        response = render(request,'sess_login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        request.session['username'] = name  # save session key in server
        response = HttpResponseRedirect(reverse('sess:homepage'))
    return response

将显示页面和API集中在一个view函数中,使得程序更加高内聚。假如只是url访问,显示登陆页面,假如是POST来的表单数据,则做为API,将name信息以键值对的形式存储到session中,并且重定向到个人主页。

所以登录页面的h5可以如下创建,表单的action直接定向到自己即可

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<form action="{% url 'sess:login' %}" method="post">
    <label for="name">Name: </label><input type="text" name="name" id="name" placeholder="Your name">
    <input type="submit">
</form>
</body>
</html>

session的创建,有点类似于字典数据的初始化。session的获取也是类似,创建homepage的view函数如下

def homepage(request):
    name = request.session.get('username')  # retrieve value from key
    return render(request,'sess_homepage.html',context={'name':name})

其中主页的h5文件如下,logout的路由还没完成所以先放空

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Homepage</title>
</head>
<body>
<h2>Welcome back {{ name }}</h2>
<a href="#">Logout</a>
</body>
</html>

输入名字试看看
1-login.png
成功显示个人主页,而且可以看到在302重定向的login中,设置了一个叫做sessionid的cookie
2-api.png
我们去数据库中的django_session表看看,发现多了一条记录
3-session.png
其中的session_key就是上面cookie中的sessionid,而session_data以等号结尾,是一个base64编码数据,解码以后的内容为

748d7c0fb7d38fdb9911aee3db89593ca680f569:{"username":"\u5c0f\u4ed8"}

这就是上面看到的session的字典并且中文以unicode编码方式存储。同时还加入了一个混淆串。最后是一个过期时间,默认是14天。

session的认证原理

session依赖于cookie。在创建session的时候,还会给浏览器下发一个名为sessionid的cookie。下次访问的时候将该cookie上传到服务端,服务端在数据库根据sessionid查找到session的内容。

所以如果在本地将cookie清空了,session就会失效,数据库里面的记录就变成了垃圾数据。所以不要通过删除cookie来退出登录

删除session

下面再来看退出登录,也就是使session失效的操作。一共有如下三种:

删除cookie

直接利用HttpResponse的delete_cookie操作,将sessionid这个cookie删除即可。

创建路由和view函数如下

path('logout/', views.logout, name='logout'),
def logout(request):
    response = HttpResponseRedirect(reverse('sess:login'))
    response.delete_cookie('sessionid')
    return response

然后修改主页的h5文件如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Homepage</title>
</head>
<body>
<h2>Welcome back {{ name }}</h2>
<a href="{% url 'sess:logout' %}">Logout</a>
</body>
</html>

点击logout成功跳转到登陆页面,访问主页显示如下
4-none.png
可以看到session返回的用户名为None。

删除session

当然,在服务器端删除数据也是可以的。修改上面的view函数如下

def logout(request):
    response = HttpResponseRedirect(reverse('sess:login'))
    # response.delete_cookie('sessionid')
    request.session.pop('username',None)
    return response

用删除字典key的pop方式去删除username,如果没有这个key会返回None而不会报keyerror的错。

登陆另一个用户如下
5-xiaoming.png
然后logout,再去数据库中查看,发现这个用户的记录还在,只是session内容变少了
6-xiaomingsession.png
访问主页,虽然cookie还在也同样会失败。

同时删除cookie和session

上面两个单独删除cookie或session的方式都会产生垃圾数据,所以使session失效最好的方法就是同时删除两者

修改view函数如下

def logout(request):
    response = HttpResponseRedirect(reverse('sess:login'))
    # response.delete_cookie('sessionid')
    # request.session.pop('username',None)
    request.session.flush()
    return response

创建新用户如下
7-jason.png
注意,因为上一步只是删除了服务端的session,并没有删除本地的cookie,所以这一次的sessionid和上一个一样。这个不会有什么影响。
logout以后去数据库中,发现这个sessionid对应的记录消失了,同时本地的cookie也没了
8-delete.png
9-login.png

总结

session是基于cookie的,不过在纯cookie的基础上又进了一步。因为本地只会保存sessionid,所以不用担心敏感数据泄露,或者是中文的编码问题。但是session也还有缺陷,假如客户端不是浏览器,而是一个手机应用,并不支持cookie,或者域名A的认证信息要用于域名B,也就是跨域访问,session也是做不到的。这时候就需要一个更为灵活的会话方式了,就是token。下一篇我们一起来看看token是咋回事。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值