cookie与session的区别以及在Django中的实现

cookie和session这两个词想必你们都不陌生,在HTTP交互中常常会涉及到这两个概念。可是它们的做用究竟是什么?两者之间到底有什么区别与联系呢?mysql

什么是cookie

cookie的定义

根据百度百科的定义:Cookie,类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(一般通过加密)。web

用大白话说,就是:sql

  1. cookie是由服务器(web应用)生成,保存在客户端(用户浏览器)上的一段数据。
  2. 该数据用于进行session跟踪。
  3. 浏览器在后续对同一网站的请求中,都必须带上该cookie。

cookie的用途

由于HTTP是无状态的协议,每一次请求之间都是彻底独立的。但为了实现web应用的交互,必须将同一个用户的屡次请求关联起来,才能产生有意义的行为。数据库

最典型的例子就是网购时添加商品到购物车,既然HTTP是无状态协议,那么服务器怎么知道商品应该添加到哪一个用户的购物车中呢?这就是cookie的做用了。django

cookie使用场景1:用户登陆

用户成功登陆电商网站后,服务器会生成一个登陆凭据,并经过response header中的 Set-Cookie 字段将其返回给用户浏览器,通知其保存该cookie信息。编程

# 用于举例,实际的cookie是通过加密的
Set-Cookie: uid=1
复制代码

浏览器通常默认会将该cookie保存在用户电脑某个目录下的一个文本文件中,后续对该网站发起的request header中,都会携带该cookie。浏览器

这样服务器在收到用户请求的同时,也能够从请求携带的cookie中知道该请求是来自哪一个用户了。这样就实现了用户登陆状态的保持。缓存

cookie使用场景2:购物车商品添加

用户添加商品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是服务端上对一个请求用户进行标识的惟一信息,并将session的信息经过cookie返回给用户,这样就实现了在用户端和服务端对用户会话的跟踪。

cookie和session的区别与联系

  1. cookie是保存在客户端的,好比用户电脑上,一般是保存在一个文本中;而session是保存在服务端的,一般保存在数据库或者缓存中,也能够保存在文件系统中。

  2. cookie是HTTP协议中的概念,位于request header中,服务器能够经过response header中的Set-Cookie字段设置和修改返回给客户端的cookie;而session是一个服务端层面的概念,不通的编程语言可能有不一样的实现方式,其目的都是为了记录保持用户的状态。

  3. 咱们常说的session会话保持,实际上就是经过借助cookie的特性,将服务端保存的session状态返回给客户端,并在整个用户会话过程当中经过cookie进行持续的交互,进而实现抽象层面的session会话保持。

因此说cookie自己并无和session有必然的联系,它只是咱们用来实现session跟踪的一种经常使用手段。

Django中的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无状态协议的会话保持,用户也就能够进行愉快的页面交互了。

相关文章
相关标签/搜索