资讯专栏INFORMATION COLUMN

Django session源码阅读

Profeel / 3410人阅读

摘要:初步的猜想是第一次和第二次请求间隔太短,数据还没有存进,到时读取失败,带着这样的疑问,阅读了的源码。源码非常简单,没有复杂的数据结构和算法,读起来没费什么劲。当过期后,用户获取的就为空,就会为用户重新初始化生成。

欢迎大家访问我的博客,查看更多内容。 背景
最近在做djnago开发时,遇到一个session问题,过程如下,第一个POST请求时,把数据存放在session,在第二次POST时,从session中读取数据,完成用户注册。在实际的环境中,发现有时第二次获取到的数据为空。初步的猜想是第一次和第二次请求间隔太短,数据还没有存进mysql,到时读取失败,带着这样的疑问,阅读了django session的源码。
django session源码非常简单,没有复杂的数据结构和算法,读起来没费什么劲。
session总体结构

session目录结构如下图

backends这个目录中定义了session的数据结构和几种存储模式

base.py这个定义了session的类dict的数据结构

cache.py定义了session的缓存存储,缓存从django.core.cache中获取

cached_db.py定义了session的缓存+数据库存储方式

db.py定义了session的数据库存储方式

file.py定义了session的文件存储

signed_cookies.py定义了用于签名的session存储方式

middleware.py实现了session中间件的处理过程

models.py定义了session数据库结构

management中是一个工具脚本,作用是清理session

session处理流程 中间件流程

处理请求前

从配置文件SESSION_ENGINE中导入session存储方式

从用户cookie中读取session_key

把session存储方式赋值给request.session

返回请求前

读取是否修改session的标志

读取session的过期时间

判断如果session被标志位修改或者配置文件中指定了SESSION_SAVE_EVERY_REQUEST,在状态码不为500时,存储session,设置用户cookie

session数据库结构

models.py定义了基于django.db.models session的数据库表结构,以及存储的方法,如果session的value为空的话,则删除该session,否则把session插入到数据库。
session的表名为django_session,三个字段分别是sessin的key,value以及过期时间

session处理流程

session初始化,根据session key获取session内容

从cookie中读取session_key,初始化session,并赋值给request.session

根据cookie中的内容初始化session_key,session的两个标志位access和modify为false

初始化session为python dcit,如果已经初始化了,则直接返回该session,如果session_key为None,或者设置no_load标志为True,则直接返回个空dict,如果session_key不为None并且设置no_load标志为False,则load数据

如果本地数据库已经存在该session,则导入到内存,如果不存在,则创建session

  - 第一步,生成sessin_key,生成算法如下:
  
          def _get_new_session_key(self):    
          while True:
              session_key = get_random_string(32, VALID_KEY_CHARS)
              if not self.exists(session_key):
                  break
          return session_key```
      这边有个问题,但用户量上百万时,这个生成算法随机重复的概率还是挺高的,所以这地方可以根据自己的需求做适当的优化
  - 第二步:保存session到数据库
  - 第三步:初始化session为空

session的操作

session为类dict结构,可以像操作dict一样操作session

session的存储,修改session内容

在返回用户请求时,根据session.access和session.modify标志位设置用户cookie和存储session,如果sesssion.access则设置用户cookie

如果session.modify为True或者设置setting.SESSION_SAVE_EVERY_REQUEST为True,则先获取过期时间,如果http状态不为500,则保存session到数据库,并设置用户cookie

上述可见,session的过期是靠设置cookie的过期时间来实现的。当cookie过期后,用户获取的session_key就为空,就会为用户重新初始化生成session。那这样就会出现一个问题,旧的session_key就会越来越多,随机生成新session_key就越难,因此django提供了一个清理的工具在management目录下,官方的说法如下

   Can be run as a cronjob or directly to clean out expired sessions (only with the database backend at the moment).
   

sesssion加密过程

session加密只是对session value值进行加密,加密的步骤为

序列化session value

设置加密salt为django.contrib.session+当前类名

使用django.utils.crypto.salted_hmac进行加密

把加密字符串进行base64编码,并转换为ascii编码,形成最终结果

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45314.html

相关文章

  • 3-django——视图

    摘要:概述作用视图接收请求并返回响应本质视图就是一个函数,被定义在文件中响应可以是一个页面,一个重定向,一个错误一个数据等等过程视图函数对象概述服务器接收到协议的请求后,会根据报文创建对象视图函数的一个形参就是对象属性方法如果请求是通过类发起的, 概述 作用:视图接收WEB请求并返回WEB响应本质: 视图就是一个python函数,被定义在views.py文件中 响应: 可以是一个HTML页面...

    dinfer 评论0 收藏0
  • 个人博客三|首页后台开发

    摘要:声明本渣渣部分代码参考自其实有很多代码是不需要自己一行行码出来,生产力是第一位。只有研究型人才需要生产代码,作为一名渣渣拿来用是最高效的做法。程序员都有一个开源的精神,码出来的代码本身是希望更多的人用到,应用到生产中。 声明:本渣渣部分代码参考自TendCode其实有很多代码是不需要自己一行行码出来,生产力是第一位。只有研究型人才需要生产代码,作为一名渣渣拿来用是最高效的做法。程序员都...

    zorpan 评论0 收藏0
  • 个人博客三|首页后台开发

    摘要:声明本渣渣部分代码参考自其实有很多代码是不需要自己一行行码出来,生产力是第一位。只有研究型人才需要生产代码,作为一名渣渣拿来用是最高效的做法。程序员都有一个开源的精神,码出来的代码本身是希望更多的人用到,应用到生产中。 声明:本渣渣部分代码参考自TendCode其实有很多代码是不需要自己一行行码出来,生产力是第一位。只有研究型人才需要生产代码,作为一名渣渣拿来用是最高效的做法。程序员都...

    姘搁『 评论0 收藏0
  • 3-Django视图

    摘要:概述作用视图接收请求并返回响应方法就是在视图里使用函数处理请求。 概述 作用:视图接收WEB请求并返回WEB响应方法:1. FBV(function base views) 就是在视图里使用函数处理请求。 ​ 2. CBV(class base views) 就是在视图里使用类处理请求。 响应: 可以是一个HTML页面,一个重定向,一个404错误、一个...

    asoren 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<