Django Session

Cookie & Session

由于HTTP协议的无状态性,每次连接结束后HTTP连接都会自动断开,因此每一个来自客户端浏览器的请求都是独立的。由于无法保存用户的访问状态,后端服务无法判断当前请求和之后的请求是不是来自同一个用户。对于静态网站而言这并不是什么问题,但是对于动态Web应用,无法识别用户身份并保持用户状态则时致命的,因为根本无法提供服务。

比如,用户必须经过登录之后才能使用Web应用提供的功能,用户首次通过账户和密码登录成功后,对于HTTP而言是无法将认证成功的用户状态通过协议层面进行保存的。那么当用户再次再次请求时,Web服务器如何得知该请求是哪个用户发起的呢?

用户登录管理

为了保持HTTP连接状态,Web服务器会通过客户端浏览器在用户本地机器磁盘上限定的位置写入用户相关的数据,这也就是所谓的Cookie。通过Cookie可以保存比如用户名、浏览记录、表单记录、登录注销等数据。但这种方式最大的弊端是非常不安全,由于Cookie是保存在用户机器上的,如果这些Cookie信息被伪造或串改或是删除,则会造成极大地安全隐患。

Cookie

Cookie的工作流程

  1. 客户端向服务器发起一个HTTP请求建立连接
  2. 服务器在HTTP响应头中添加Set-Cookie的键值对
  3. 客户端在随后的HTTP请求头中添加Cookie首部,内容包含之前服务器响应中设置的Cookie信息。
  4. 服务端根据Cookie首部获取用户信息
Set-Cookie:sessionid=a92d67e44a9b92d7dafca67e507985c0;
expires=Thu, 07-Jul-2011 04:16:28 GMT;
Max-Age=1209600;
Path=/

因此,现代浏览器使用Cookie只会保存一些对用户而言不太重要的数据,实际的用户状态等数据则会以Session会话的形式保存在服务端。简单来说Session就是服务端的Cookie。也就是将用户数据和状态保存在远程服务器中,这远比保存在客户端更加安全、方便和快捷。

服务端的Session中会存储特定用户会话所需的属性和配置信息,当用户在应用程序的页面之间跳转时,储存在Session中的数据将不会丢失,一直会在用户会话过程保存。因此,Session会话可以看作是客户端与服务端沟通的一种工具。

服务端的Session是需要依赖于客户端的Cookie的,与Cookie不同的Session将重要的用户状态数据保存在服务端,而Cookie只会保存一些非明文的识别信息,比如哈希值。

为什么说Session是服务端的Cookie呢?

Session的底层是基于Cookie技术来实现的,在早期存储会话状态一直使用的是Cookie,客户端的Cookie中保存着明文的键值对,由于直接保存重要的用户数据是不安全的,其后才衍生出Session。Session是加密后的Cookie键值。

当用户通过客户端浏览器发送请求访问远程Web服务器应用程序指定的页面时,如果客户端还没有会话,Web服务器会自动为其创建一个Session会话对象,并且为每个Session对象分配一个唯一的sessionid。Session对象创建成功后,Web服务器通过传递一个名字为SESSIONID的Cookie将这个sessionid返回给浏览器。

当用户再次访问Web服务器时,会携带上具有sessionid的Cookie一并发送给Web服务器。Web服务器通过不同的sessionid来查询出与之对应的Session对象,通过Session对象为用户提供不同的服务。如果当用户会话过期或被放弃后,Web服务器也会终止该会话。

Session

比如:PHP中利用Cookie来管理Session的方式

PHP利用Cookie管理Session

Django Session

Django内置了通用的Session会话框架,并提供了多种Session数据保存的方式,分别是数据库、缓存、文件、缓存+数据库、加密Cookie。Djaong默认会将Session保存到名为django_session的数据表中。没有特别要求,尽量不要将Session保存到Cookie之中。如果从性能能上考虑的话,基于缓存的会话会更优。

启用Session

在Django项目中启用Session框架

  • 在项目配置的MIDDLEWARE_CLASSES中间件类中添加SessionMiddleware会话中间价
  • 在项目配置的INSTALLED_APPS注册sessions框架

Django通过内置的SessionMiddleware中间件实现会话功能,要启动会话就必须先开启该中间件。

$ vim settings.py
MIDDLEWARE_CLASSES = [
  "django.contrib.sessions.middleware.SessionMiddleware"
]
INSTALLED_APPS = [
  "django.contrib.sessions"
]

Session配置

在项目配置文件中可以添加会话配置选项

会话配置 默认值 描述
SESSION_ENGINE django.contrib.sessions.backends.db 设置Session引擎
SESSION_FILE_PATH None 缓存Session文件的路径
SESSION_COOKIE_NAME sessionid Session在浏览器中存储的键名
SESSION_COOKIE_PATH / Session应用的路径默认为全站
SESSION_COOKIE_DOMAIN None Session应用的站点域名
SESSION_COOKIE_SECURE False 是否允许使用HTTPS传输Cookie
SESSION_COOKIE_HTTPONLY True 是否仅能使用HTTP传输Session的Cookie
SESSION_COOKIE_AGE 43200 Session的存活时长
SESSION_EXPIRE_AT_BROWSER_CLOSE True 关闭浏览器时是否清除Session
SESSION_SAVE_EVERY_REQUEST False 每次请求是否重新生成并保存Session

Session引擎

  • 基于数据库的会话
SESSION_ENGINE = django.contrib.sessions.backends.db

默认Django将会话数据保存在数据库,并通过django.contrib.sessions.models.Session模型创建django_session数据表。

CREATE TABLE `django_session` (
  `session_key` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
  `session_data` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `expire_date` datetime(6) NOT NULL,
  PRIMARY KEY (`session_key`),
  KEY `django_session_expire_date_a5c62663` (`expire_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
django_session
  • 基于缓存的会话
SESSION_ENGINE = django.contrib.sessions.backends.cache
  • 基于数据库与缓存的会话
SESSION_ENGINE = django.contrib.sessions.backends.cache_db
  • 基于文件的会话
SESSION_ENGINE = django.contrib.sessions.backends.file

必须配置SESSION_FILE_PATH,默认使用tempfile.gettempfile()获取临时文件目录,作为Session文件的保存目录,同时需要具有读写权限。

  • 基于加密Cookie的会话
SESSION_ENGINE = django.contrib.sessions.backends.signed_cookies

Django使用加密签名工具和安全密钥设置保存会话的Cookie

Session中间件

Django的中间件框架是Django处理请求和响应的一套钩子函数的集合。传统Django视图模式是"HTTP请求 > View > HTTP响应",加入中间件框架后视图模式则变为"HTTP请求 > 中间件处理 > app > 中间件处理 > HTTP响应"。

Session操作

Session操作 描述
request.session["key"] = "value" 设置键名为key的会话的键值
request.session.setdefault("key", "value") 设置会话键值对字典{"key":"value"}
value = request.session["key"] 获取会话中建名为key的键值
value = request.session.get("key", None) 获取会话中键名为key的键值若不存在则默认为None
del request.session["key", "value"] 删除指定键值对的Cookie
request.session.delete() 删除当前请求下的所有Session但不删除Cookie
request.session.flush() 删除当前请求下所有Session同时删除Cookie
keys = request.session.keys() 获取Session中所有键名返回字典
values = request.session.values() 获取Session中所有键值返回字典
items = request.session.items() 获取所有键值对返回字典
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342