cookie和session这两个词想必你们都不陌生,在HTTP交互中常常会涉及到这两个概念。可是它们的做用究竟是什么?两者之间到底有什么区别与联系呢?mysql
根据百度百科的定义:Cookie,类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(一般通过加密)。web
用大白话说,就是:sql
由于HTTP是无状态的协议,每一次请求之间都是彻底独立的。但为了实现web应用的交互,必须将同一个用户的屡次请求关联起来,才能产生有意义的行为。数据库
最典型的例子就是网购时添加商品到购物车,既然HTTP是无状态协议,那么服务器怎么知道商品应该添加到哪一个用户的购物车中呢?这就是cookie的做用了。django
用户成功登陆电商网站后,服务器会生成一个登陆凭据,并经过response header中的 Set-Cookie 字段将其返回给用户浏览器,通知其保存该cookie信息。编程
# 用于举例,实际的cookie是通过加密的
Set-Cookie: uid=1
复制代码
浏览器通常默认会将该cookie保存在用户电脑某个目录下的一个文本文件中,后续对该网站发起的request header中,都会携带该cookie。浏览器
这样服务器在收到用户请求的同时,也能够从请求携带的cookie中知道该请求是来自哪一个用户了。这样就实现了用户登陆状态的保持。缓存
用户添加商品A到其购物车时,服务器能够修改cookie字段,将商品A的信息追加到cookie中,这样就实现了将商品A与用户关联到一块儿的行为。bash
Set-Cookie: uid=1;prod=A
复制代码
当用户又添加了商品B到购物车中时,服务器又会将商品B的信息追加到cookie中。服务器
Set-Cookie: uid=1;prod=A; prod=B
复制代码
等到用户结帐的时候,服务器就能够从请求携带的cookie中获取到该用户选择的全部商品信息。
咱们常说的session,实际上有两层概念。
首先是它的抽象概念:在用户端与服务端之间一对一连续的交互,抽象为一个用户会话,也就是session。好比从用户登陆到登出之间进行的一系列交互,都属于同一个session。
其次是它的实际概念:为了实现用户会话的保持,服务端经过建立session对象记录了用户登陆后的各类信息,好比用户名,用户的操做等等。
session是服务端上对一个请求用户进行标识的惟一信息,并将session的信息经过cookie返回给用户,这样就实现了在用户端和服务端对用户会话的跟踪。
cookie是保存在客户端的,好比用户电脑上,一般是保存在一个文本中;而session是保存在服务端的,一般保存在数据库或者缓存中,也能够保存在文件系统中。
cookie是HTTP协议中的概念,位于request header中,服务器能够经过response header中的Set-Cookie字段设置和修改返回给客户端的cookie;而session是一个服务端层面的概念,不通的编程语言可能有不一样的实现方式,其目的都是为了记录保持用户的状态。
咱们常说的session会话保持,实际上就是经过借助cookie的特性,将服务端保存的session状态返回给客户端,并在整个用户会话过程当中经过cookie进行持续的交互,进而实现抽象层面的session会话保持。
因此说cookie自己并无和session有必然的联系,它只是咱们用来实现session跟踪的一种经常使用手段。
Django是经过中间件的形式支持session的。在建立项目时默认就会在settings.py中配置好session中间件。
INSTALLED_APPS = [
'django.contrib.sessions',
]
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
复制代码
Django默认会将session信息保存在数据库中,能够经过 manage.py migrate 生成session信息表。若是对性能要求比较高,也能够将session信息配置保存到缓存中。
mysql> desc django_session;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| session_key | varchar(40) | NO | PRI | NULL | |
| session_data | longtext | NO | | NULL | |
| expire_date | datetime(6) | NO | MUL | NULL | |
+--------------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
复制代码
能够看到,django_session表中有3个字段,其中:
session_data 实际对用户信息进行加密后生成的密文,能够解密;
session_key是根据session_data密文生成的一串随机字符串,自己并没有实际意义,仅用于插入到cookie中返回给客户端,并在用户发起请求时对请求中携带的cookie与django_session表中的session_key进行匹配,查询是否有匹配的session_data;
expire_date记录了该session的过时时间。
在发起登陆请求后,服务端在response header中携带了Set-Cookie字段,内容包含了csrftoken,以及本次会话的sessionid。
(cookie中的csrftoken机制请见 CSRF攻击与Django防范)
Set-Cookie: csrftoken=ATfjCEJZVaN9zTYnSHPzSRJhWfVfFlxntOYyu2f64j4mf9clzigVxsBIFN293uu3; expires=Sun, 28 Feb 2021 14:58:22 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=j0b9jsiiumwfjzmt9k3tw05aw7q5xk2n; expires=Sun, 15 Mar 2020 14:58:22 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
复制代码
在Django数据库中,能够看到django_session表中也有对应的记录
在登陆后的下一次请求中,能够看到request header中的cookie中已经携带了服务端返回的sessionid
至此,经过服务端的session机制,并借助HTTP协议的cookie机制,就实现了HTTP无状态协议的会话保持,用户也就能够进行愉快的页面交互了。