Django框架之Cookie和Session
一、cookie与session的发展史
Cookie和Session是Web开发中常用的两种机制,用于在客户端和服务器之间存储和管理用户信息。
1、Cookie的发展史:
- 1994年:由Netscape公司的工程师Lou Montulli发明。最初的目的是为了解决HTTP协议的状态管理问题,使网站能够在浏览器端存储和读取用户信息。
- 1997年:随着HTTP 1.1协议的发布,Cookie被正式纳入HTTP标准。
- 2000年代:随着Web应用程序的发展,Cookie被广泛应用于跟踪用户会话、存储用户偏好设置等方面。
2、Session的发展史
- 1990年代末:由于Cookie的一些局限性(如存储容量有限、安全性问题等),Web开发者开始寻找替代方案。
- 2000年代初:Session机制应运而生,它将用户信息存储在服务器端,而仅在客户端保存一个会话标识(通常是一个Cookie),用于唯一标识用户会话。
- 2000年代中后期至今:Session机制逐渐成为Web开发中常用的用户状态管理方式,特别是在处理敏感信息和安全性要求较高的场景中。
3、Cookie和Session的结合使用
- 在实际应用中,通常会将Session ID 存储在Cookie中,以便服务器能够识别和管理用户会话。
- Cookie和Session通常结合使用,Cookie用于在客户端存储少量信息(如Session ID),而Session则用于在服务器端存储更多的用户信息。
总的来说,Cookie和Session在Web开发中扮演着不可或缺的角色,它们的发展历程反映了对于用户状态管理的不断探索和改进,以提供更好的用户体验和安全性保障。
二、Cookie与Session
1、为什么会有Cookie与Session?
cookie和session诞生的前提是因为http协议是无状态的。
早期的网站都没有保存用户功能的需求,所有用户访问返回的结果都是一样的。
以登录为例,如果不保存用户登录状态,也就意味着用户每次访问网站都需要重复的输入用户名和密码,这样的操作太麻烦了。
于是出现了各种解决方案:
(1) 解决方案一(保存在本地)
当用户第一次登陆成功之后,将用户的用户名和密码返回给用户浏览器,让用户浏览器保存在本地,之后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取之后自动验证。
- 缺点:安全隐患非常大
(2) 解决方案二(保存在浏览器)
当用户登陆成功之后,服务端产生一个随机字符串(在服务端保存数据,用k:v键值对的形式),交由客户端浏览器保存。
随机字符串1:用户1相关信息
随机字符串2:用户2相关信息
随机字符串3:用户3相关信息
之后访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串从而获取到对应的用户信息。
- 缺点:如果你截取到了该随机字符串,你就可以冒充当前用户,还是具有安全隐患
在web领域没有绝对的安全也没有绝对的不安全
2、Cookie介绍
(1)定义
Cookie是一小段文本信息,由服务器发送到用户的浏览器,然后存储在用户的计算机上。每当用户加载网站时,浏览器会将相关的Cookie信息发送回服务器。 服务端保存在客户端浏览器上的信息都可以称之为cookie。
(2)特点
-
它的表现形式一般都是k:v键值对(可以有多个)
-
存储在客户端,通常是在用户的浏览器中。
-
可以存储少量的数据(通常4KB左右)。
-
可以设置过期时间,可以是会话级的(浏览器关闭后失效)或持久性的(在一定时间后失效)。
-
可以被浏览器禁用或删除,用户可以控制Cookie的存储和传输。
(3)用途
- 跟踪用户会话状态,实现用户登录状态的保持。
- 存储用户偏好设置,如语言偏好、主题等。
- 支持广告追踪和个性化推荐等功能。
3、Session介绍
(1)定义
Session是一种在服务器端存储用户信息的机制,通过在客户端存储一个会话标识(通常是一个Cookie),来唯一标识用户的会话状态。
(2)特点
-
它的表现形式一般也是k:v键值对(可以有多个)
-
存储在服务器端,客户端仅存储会话标识。
-
可以存储大量的数据,不受浏览器存储容量限制。
-
通常在服务器内存或数据库中存储,因此比Cookie更安全。
-
会话结束时,数据通常会被自动清除。
(3)用途
- 存储用户登录信息和权限验证。
- 保存用户购物车内容和交易信息。
- 在多个页面间共享用户信息。
3、token介绍
Token是在计算机科学领域中广泛使用的概念,通常用于身份验证、授权和安全目的。以下是关于Token的详细介绍:
(1)什么是Token?
- 定义:Token是一种代表特定实体(用户、设备、应用程序等)的唯一标识符。token的工作原理就是是服务端不再保存数据,而是登陆成功之后,将一段用户信息进行加密处理(加密算法只有自己知道),然后将加密之后的结果拼接在信息后面,整体返回给浏览器保存,最后浏览器下次访问的时候带着该信息,服务端自动切去前面一段信息并再次使用自己的加密算法跟浏览器尾部的密文进行比对、
(2)Token的类型
-
访问令牌(Access Token):用于验证用户身份并获取访问权限。常用于OAuth认证流程中,用户通过认证服务器获得访问令牌,然后用于访问受保护的API。
-
刷新令牌(Refresh Token):用于获取新的访问令牌。当访问令牌过期或失效时,可以使用刷新令牌来获取新的访问令牌,而无需用户重新登录。
-
身份令牌(Identity Token):包含关于用户身份信息的令牌。常用于身份验证和用户信息传递。
-
JSON Web Token(JWT):一种开放标准(RFC 7519),定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息。JWT通常用作访问令牌。
(3)Token的作用
-
身份验证:Token可用于验证用户身份,确保用户有权访问受保护资源。
-
授权:Token可以用于授权用户访问特定资源或执行特定操作。
-
安全性:Token可以增加系统的安全性,减少敏感信息的传输。
(4)Token的优势
-
无状态性:Token机制使得服务器无需保存会话信息,减轻了服务器负担。
-
可扩展性:Token机制适用于分布式系统和微服务架构,易于扩展和集成。
(5)Token的安全性考虑
-
令牌泄露:泄露Token可能导致未经授权的访问,因此需要采取措施确保Token的安全性。
-
过期时间:合理设置Token的过期时间,避免长时间有效导致安全风险。
总的来说,Token是一种重要的身份验证和授权机制,在网络安全和用户身份管理中扮演着关键角色。开发人员在设计和实现应用程序时,应充分考虑Token的安全性和合理性,以确保系统的安全性和稳定性。
4、总结
- cookie就是保存在客户端浏览器上的信息
- session就是保存在服务端上的信息
- session是基于cookie工作的(其实大部分的八寸用户状态的操作都需要使用到cookie)
三、Django操作Cookie
虽然cookie是服务端告诉客户端浏览器需要保存内容,但是客户端浏览器可以选择拒绝保存,如果禁止了,那么只要是需要记录用户状态的网站登陆功能都无法使用了
1、引入
(1)视图函数的返回值(三板斧)
return HttpResponse() return render() return redirect()
(2)改变形式来操作Cookie
如果你想要操作cookie,你就不得不利用obj对象
obj1 = HttpResponse() # 操作cookie return obj1 obj2 = render() # 操作cookie return obj2 obj3 = redirect() # 操作cookie return obj3
2、操作Cookie
(1)设置cookie
obj = HttpResponse() obj.set_cookie(key,value) return obj
(2) 加盐
obj = HttpResponse() obj.set_signed_cookie(key,value,salt='盐') return obj
(3)获取cookie
request.COOKIES.get(key)
(4)获取加盐的cookie
request.get_signed_cookie(key,salt='盐')
(5)设置超时时间
- 在设置cookie的时候可以添加一个超时时间
obj.set_cookie('username', 'xiao666', max_age=3,expires=3)
- max_age
- 设置超时时间,以秒为单位
- expiress
- 设置超时时间 针对IE浏览器使用,以秒为单位
(6)注销cookie
# 主动删除cookie(注销功能) @login_auth def logout(request): obj = redirect('/login/') obj.delete_cookie('username') return obj
3、具体案例
实现一个真正的登录功能
思路:首先创建一个校验用户是否登录的装饰器,用户如果在没有登录的情况下想访问一个需要登录的页面,那么应该先跳转到登录页面,然后当用户输入正确的用户名和密码之后就应该跳转到用户之前想要访问的页面去,而不是直接写死。
# 校验用户是否登录的装饰器 def login_auth(func): def inner(request, *args, **kwargs): # print(request.path_info) # print(request.get_full_path()) # 能够获取到用户上次想要访问的url target_url = request.get_full_path() if request.COOKIES.get('username'): return func(request, *args, **kwargs) else: return redirect(f'/login/?next={target_url}') return inner def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'xiao' and password == '123': # 获取用户上一次想要访问的url target_url = request.GET.get('next') # 这个结果也可能是None # 针对上一次用户访问的url做出判断 if target_url: obj = redirect(target_url) else: # 保存用户登录状态 obj = redirect('/home/') # 让浏览器记录cookie数据 obj.set_cookie('username', 'xiao666') """ 浏览器不单单会帮你存,而且后面每次访问你的时候还会带着它过来 """ return obj return render(request, 'login.html')
四、Django操作session
1、引入
session数据是保存在服务端的,给客户端返回的是一个随机字符串。
- 格式:
sessionid:随机字符串
在默认情况下操作session的时候需要Django默认的一张django_session表。因此首先数据库迁移命令,生成django_session表。
django默认session的过期时间14天,但是也可以人为的修改。
2、操作Session
(1)设置session
request.session['key'] = value
(2)设置session内部发生了哪些事
- django内部会自动帮你生成一个随机字符串
- django内部自动将随机字符串和对应的数据存储到django_session表中
- 先在内存中产生操作数据的缓存
- 在响应结果django中间件的时候才真正的操作数据库
- 将产生的随机字符串返回给客户端浏览器保存
(3)获取Session
request.session.get('key')
(4)获取session内部发生了哪些事
- 自动从浏览器请求中获取session对应的随机字符串
- 拿着该随机字符串去django_session表中查找对应的数据
- 如果比对上了,则将对应的数据去除并以字典的形式封装到request.session中
- 如果比对不上,则request.session.get()返回的是None
(5)设置/获取session多个值
- 虽然给session设置多个值的时候,存在数据库中的数据仍是一条
- 但是在取session的时候,可以通过
request.session
对象获取到设置的多组键值对
(6)设置过期时间
request.session.set_expiry()
括号内可以放四种类型的参数:
- 整数 多少秒就失效
- 日期对象 到指定日期就失效
- 0 一旦当前浏览器窗关闭就立刻失效
- 不写 失效时间就取决于django内部全局session默认的失效时间(也就是14天)
(7)清除session
# 方式一 request.session.delete() # 只删服务端 # 方式二 request.session.flush() # 浏览器和服务端都清空(推荐使用)
方式一用于删除当前用户的Session数据,但会保留Session的Key。这意味着Session对象本身仍然存在,但其中的数据将被清空。下次访问时,如果Session没有被重新填充,则会得到一个空的Session对象。
方式二用于完全删除当前用户的Session,包括Session对象和所有相关数据。下次访问时,将创建一个新的空Session对象。
(8)保存session
1. 数据库Session SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 2. 缓存Session SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 3. 文件Session SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 4. 缓存+数据库 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 5. 加密Cookie Session SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 其他公用设置项: SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认) SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
3、django_session表中的数据
django_session表中的数据条数是取决于浏览器的,
- 同一个计算机上(IP地址)同一个浏览器只会有一条数据生效,主要是为了节省服务端数据库资源
- 同一个计算机(IP地址)上多个浏览器会有多个数据生效
当session过期的时候可能会出现多条数据对应一个浏览器,但是该现象不会出现很久,内部会自动识别过去的数据清除,也可以自己书写代码清除。
4、具体案例
(1)简单版
- 路由
# session操作 path('set_session/', views.set_session),
- 视图
def set_session(request): request.session['sign'] = "369" return HttpResponse("返回消息")
- 会报错
OperationalError at /set_session/ no such table: django_session
- 数据是保存在服务端的
- 在默认情况下操作session的时候需要Django默认的一张
django_session
表- 数据库迁移命令时
- Django会默认创建很多表,其中就有
django_session
表- Django默认session的过期时间是14天
- 但是我们可以认为的修改过期时间
(2)解决办法
- 先进行数据库迁移命令
- 再进行访问
- session 会自动保存到
django_session
表中
(3)优化
- 路由
# session操作 path('set_session/', views.set_session), path('get_session/', views.get_session),
- 视图
def set_session(request): request.session['sign'] = "369" return HttpResponse("返回消息") def get_session(request): request.session.get("sign") return HttpResponse("拿取成功消息")
五、会话session补充
1、前言引入
(1)HTTP特性之无状态
- 因为因特网HTTP协议的特性,每一次来自于用户浏览器的请求(request)都是无状态的、独立的。
- 通俗地说,就是无法保存用户状态,后台服务器根本就不知道当前请求和以前及以后请求是否来自同一用户。
- 对于静态网站,这可能不是个问题,而对于动态网站,尤其是京东、天猫、银行等购物或金融网站,无法识别用户并保持用户状态是致命的,根本就无法提供服务。
- 你可以尝试将浏览器的cookie功能关闭,你会发现将无法在京东登录和购物。
(2)解决连接方案(Cookie)
- 为了保持连接状态,网站会通过用户的浏览器在用户机器内被限定的硬盘位置中写入一些数据,也就是所谓的Cookie。
- 通过Cookie可以保存一些诸如用户名、浏览记录、表单记录、登录和注销等各种数据。
- 但是这种方式非常不安全,因为Cookie保存在用户的机器上,如果Cookie被伪造、篡改或删除,就会造成极大的安全威胁,因此,现代网站设计通常将Cookie用来保存一些不重要的内容,实际的用户数据和状态还是以Session会话的方式保存在服务器端。
(3)解决数据安全方案(Session)
-
Session就是在服务器端的‘Cookie’,将用户数据保存在服务器端,远比保存在用户端要安全、方便和快捷得多。
-
Session依赖Cookie!但与Cookie不同的地方在于Session将所有的数据都放在服务器端,用户浏览器的Cookie中只会保存一个非明文的识别信息,比如哈希值。
-
Session是大多数网站都需要具备的功能。Django为我们提供了一个通用的Session框架,并且可以使用多种session数据的保存方式:
-
保存在数据库内
-
保存到缓存
-
保存到文件内
-
保存到cookie内
-
-
通常情况,没有特别需求的话,请使用保存在数据库内的方式,尽量不要保存到Cookie内。
(4)扩展
- Django的session框架支持匿名会话,封装了cookies的发送和接收过程。
- cookie包含一个会话ID而不是数据本身(除非你使用的是基于后端的cookie)。
- Django的会话框架完全地、唯一地基于Cookie。
- 它不像PHP一样,把会话的ID放在URL中。
- 那样不仅使得URL变得丑陋,还使得你的网站易于受到通过"Referer"头部进行窃取会话ID的攻击。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类