django session源码剖析
首先要明白,session和cookie,session是保存在服务器端,cookie存储在浏览器上,我们称为客户端,客户端向服务端发送请求时,会将cookie一起发送给服务端。服务端接收到请求后,会去检查是否已经有该客户端的session信息,如果没有,则创建一个新的session对象,用于保存客户端的一些必要信息,如果从服务器上找到了该客户端的信息,则会将该信息加载到session里,
django之所以能实现登陆认证,依靠的是一个叫sessionid的东西,该id记录了你的认证信息,如果你不喜欢这个名称,你也可以通过修改settings配置SESSION_COOKIE_NAME
settings解说之session
# Cache to store session data if using the cache session backend.
SESSION_CACHE_ALIAS = 'default' # 这个值对应CACHES里面的key
# Cookie name. This can be whatever you want.
SESSION_COOKIE_NAME = 'sessionid'
# The module to store session data
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# class to serialize session data
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'
#########
# CACHE #
#########
# The cache backends to use.
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
. 在request请求模块里,默认是不带session功能的,也就是说request没有session属性的,为何我们还能使用呢?因为session功能是以中间件形式提供,由于在settings里配置了
MIDDLEWARE_CLASSES
这个变量,同时将模块'django.contrib.sessions.middleware.SessionMiddleware'添加到项目里,
Django1.8以后的版本改名为MIDDLEWARE
,所以我们才能通过request.session方式设置session。那么这个中间件对我们的request做了些什么呢?
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session = self.SessionStore(session_key)
class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest
def __call__(self, environ, start_response):
...
try:
request = self.request_class(environ)
...
#通过上面这段代码,可以分析,request是django.core.handlers.wsgi.WSGIRequest()的实例
#中间件首先从我们的请求request.COOKIES获取对应的cookie信息,这个信息最开始是从浏览器的cookie获取的,如果浏览器没有相应的cookie信息,则服务器会为这个浏览器创建一个cookie实例,本质上cookie对象就是一个继承了dict字典的对象,
接着从cookie对象取出session_key,也就是cookie为 `sessionid `的值,,然后拿着这个值到self.SessionStore进行实例化,
class SessionStore(SessionBase):
"""
A cache-based session store.
"""
def __init__(self, session_key=None):
self._cache = caches[settings.SESSION_CACHE_ALIAS] # 实例化时会通过settings配置加载一个用于存储缓存的媒介,该媒介用于存储session的,默认是媒介是引擎是db,即数据库,我们这里分析的是使用本地内存作为session缓存。caches会去导入settings配置的CACHES的backend存储引擎,并且做一些基本解析CACHES对应的key的参数配置,比如我们的`SESSION_CACHE_ALIAS`为default,那么会把default里的其他keys信息当成参数传到那个backend对象里进行实例化,最终赋值给session的self._cache变量
super(SessionStore, self).__init__(session_key) # 调用父类的构造方法,
@property
def cache_key(self):
return KEY_PREFIX + self._get_or_create_session_key() # 这个方法最终一定会获取到一个_session_key
def load(self):
"""
这个方法调用是在假如需要对session进行修改操作时,比如设置session操作,那么会调用父类的__setitem__方法
def __setitem__(self, key, value):
self._session[key] = value
self.modified = True
def _get_session(self, no_load=False):
"""
Lazily loads session from storage (unless "no_load" is True, when only
an empty dict is stored) and stores it in the current instance.
"""
self.accessed = True
try:
return self._session_cache
except AttributeError:
if self.session_key is None or no_load:
self._session_cache = {}
else:
self._session_cache = self.load()
return self._session_cache
_session = property(_get_session)
首先父类去获取_session属性,如果是第一次访问,肯定是没有缓存session的,也就是return self._session_cache这个对象暂时没有这个属性,第一次访问时,是没有session_key的,所以会 self._session_cache = {}创建一个空字典存储session缓存。第二次请求时,这时候可以从请求cookie里获取到 _session_key,那么,这时服务器可能已经记录过客户端的session信息了,为什么说是可能呢?因为如果选择使用本地内存方式存储,如果重启服务器,那么session将丢失,但是浏览器上已经写入了cookie信息,保留了_session_key.我们假如服务器没有重启过,那么服务器就保留了浏览器的session信息,这时会去加载这个session信息
"""
try:
session_data = self._cache.get(self.cache_key, None) #
except Exception:
# Some backends (e.g. memcache) raise an exception on invalid
# cache keys. If this happens, reset the session. See #17810.
session_data = None
if session_data is not None:
return session_data
self._session_key = None
return {}
def create(self):
# Because a cache can fail silently (e.g. memcache), we don't know if
# we are failing to create a new session because of a key collision or
# because the cache is missing. So we try for a (large) number of times
# and then raise an exception. That's the risk you shoulder if using
# cache backing.
for i in range(10000):
self._session_key = self._get_new_session_key()
try:
self.save(must_create=True)
except CreateError:
continue
self.modified = True
return
raise RuntimeError(
"Unable to create a new session key. "
"It is likely that the cache is unavailable.")
def save(self, must_create=False):
if self.session_key is None:
return self.create()
if must_create:
func = self._cache.add
else:
func = self._cache.set
result = func(self.cache_key,
self._get_session(no_load=must_create),
self.get_expiry_age())
if must_create and not result:
raise CreateError
def exists(self, session_key):
return session_key and (KEY_PREFIX + session_key) in self._cache
def delete(self, session_key=None):
if session_key is None:
if self.session_key is None:
return
session_key = self.session_key
self._cache.delete(KEY_PREFIX + session_key)
@classmethod
def clear_expired(cls):
pass
django session源码剖析的更多相关文章
- Django session 源码流程
流程 Django session源码流程 首先执行的是SessionMiddleware的init方法 import_module(settings.SESSION_ENGINE) 导入了一个 dj ...
- Django对中间件的调用思想、csrf中间件详细介绍、Django settings源码剖析、Django的Auth模块
目录 使用Django对中间件的调用思想完成自己的功能 功能要求 importlib模块介绍 功能的实现 csrf中间件详细介绍 跨站请求伪造 Django csrf中间件 form表单 ajax c ...
- Django——Session源码分析
首先我们导入django.contrib.sessions.middleware这个中间件,查看里面的Session源码 from django.contrib.sessions.middleware ...
- session源码剖析
session机制采用的是一种在客户端与服务端之间保持状态的解决方案,由于采用服务器端保持状态的方案在客户端也要保存标识,session机制也要借助于cookie机制达到目的.session保存了客户 ...
- django restfulwork 源码剖析
概要: 1.restful 规范(建议); 2. django rest framework框架 内容回顾: 1.开发模式; - 普通开发模式(前后端放在一起写) - 前后端分离 好处: 后端一套,前 ...
- Django admin源码剖析
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- 跨站请求伪造(csrf),django的settings源码剖析,django的auth模块
目录 一.跨站请求伪造(csrf) 1. 什么是csrf 2. 钓鱼网站原理 3. 如何解决csrf (1)思路: (2)实现方法 (3)实现的具体代码 3. csrf相关的装饰器 (1)csrf_p ...
- Django Rest Framework源码剖析(八)-----视图与路由
一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使 ...
- Django Rest Framework源码剖析(七)-----分页
一.简介 分页对于大多数网站来说是必不可少的,那你使用restful架构时候,你可以从后台获取数据,在前端利用利用框架或自定义分页,这是一种解决方案.当然django rest framework提供 ...
随机推荐
- [转] Mongoose初使用总结
连接mongoose mongoose连接数据库有两种方式 第一种: 'use strict'; const mongoose = require('mongoose'); mongoose.conn ...
- [转]Xshell在按delete,backspace键产生乱码(不可用)的解决方法
Xshell在按delete,backspace键产生乱码的解决方法 当我们用Xshell登录进入linux后,在普通模式下,对输入进行删除等操作没有问题. 而在运行中,按delete,backspa ...
- 常见内网IP段
以下IP段为内网IP段: 192.168.0.0 - 192.168.255.255 172.16.0.0 - 172.31.255.255 10.0.0.0 - 10.255.255.255
- 使用sparkSQL的insert操作Kudu
可以选择使用Spark SQL直接使用INSERT语句写入Kudu表:与'append'类似,INSERT语句实际上将默认使用UPSERT语义处理: import org.apache.kudu.sp ...
- js中的new Option默认选中
new Option("文本","值",true,true).后面两个true分别表示默认被选中和有效! //js默认选中 var sel = document ...
- 事件(Event)(onclick,onchange,onload,onunload,onfocus,onblur,onselect,onmuse)【转载】
ylbtech-Event:事件(Event)对象 事件(Event) HTML 4.0 事件属性 onclick onchange onload onunload onselect onmouse ...
- 20165235 实验一 Java开发环境的熟悉
20165235 实验一 Java开发环境的熟悉 课程:JAVA程序设计 姓名:祁瑛 学号:20165235 指导老师:娄嘉鹏 实验日期: 2018.4.2 实验内容:java开发环境的熟悉 一,实验 ...
- 犹记当年写出bug睡不着,回想今天只求睡好渡余生……
不想面对已经在博客园注册了3年多的时间 了,就是这么快的就已经过去了近3年的工作时间,从最开始的对编程的困惑到慢慢有一点的认识,好像哦就这样没有什么啊,也没有涉及到一些比较难的东西. 但是当初第一份工 ...
- oracle左连接连表查询
要想把该表的数据全部查出来,必须select中出现该表的字段. SELECT distinct a.ZGSWSKFJ_DM,b.ZGSWJ_DM,b.SSGLY_DM,b.NSRSBH,b.NSRMC ...
- 初心不负 笔记-JS高级程序设计-引用类型篇-Array
ES3方法集合: 1join()方法,将一个数组里面的所有元素转换成字符串,然后再将他们连接起来返回一个字符串,通过制定的符号,默认值为逗号.不会改变原数组 ,,,,]; a.join(); &quo ...