当前位置: 首页 > news >正文

57. django之Cookie和Session

1.  Cookie与Session介绍

1.1 cookie

客户端与服务端交互时,存储在客户端上与用户信息相关的数据。

Cookie是存储在用户计算机上的小型文本文件,用于跟踪用户在网站上的活动。
初始版本的Cookie只能存储很少的数据,并且没有强制加密机制,容易被篡改或窃取。

1.2 Session简介

Session是在服务端存储用户会话数据的一种技术。
每当用户访问网站时,服务器会为其创建一个唯一的Session标识符(Session ID),并将会话数据存储在服务器上。

Session ID一般通过Cookie或URL参数传递给客户端,用于识别用户的会话状态。

Session ID通过Set-Cookie发送给浏览器(Cookie 名通常为JSESSIONID或PHPSESSID)。
浏览器存储 Session ID:浏览器将包含Session ID的 Cookie 保存为会话 Cookie

1.3 Cookie和Session的关联

在实际应用中,Cookie和Session通常结合使用。

当用户首次访问网站时,服务器会为其分配一个唯一的Session ID,通过Set-Cookie发送给浏览器,。
随后,客户端在每次请求中都会携带该Cookie,服务器通过解析Cookie中的Session ID,读取对应的会话数据,实现用户状态的跟踪和管理。

1.4 token

Token 身份验证是无状态的分布式身份认证方案,核心是:服务器不存储用户会话状态,所有身份信息都加密编码在客户端持有的 Token 字符串中,每次请求由服务器验证 Token 的合法性来完成身份校验。

客户端                          服务器|                              |
1. 提交用户名/密码登录请求 -----> ||                              ||                          2. 验证用户凭证|                              || <----- 3. 生成并返回签名Token ||                              |
4. 本地存储Token(localStorage/sessionStorage/HttpOnly Cookie)|                              |
5. 后续请求携带Token(Authorization: Bearer <token>| ----->                       ||                              ||                          6. 验证Token签名+有效期|                              || <----- 7. 返回受保护资源/401未授权 |

token最主流实现:JWT(JSON Web Token)

JWT 是目前 Web 领域最通用的 Token 标准(RFC 7519),本质是三段式 Base64 编码字符串,用.分隔,格式:Header.Payload.Signature
部分作用内容示例关键说明
Header(头部) 声明 Token 类型和签名算法 {"alg":"HS256","typ":"JWT"} 固定 Base64 编码,任何人可解码
Payload(载荷) 存储身份信息和声明 {"sub":"123456","name":"张三","exp":1714000000} 仅 Base64 编码,绝对不能放密码、手机号等敏感信息
Signature(签名) 防篡改核心 HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload), secret) 用服务器私钥 / 密钥生成,只有服务器能验证

签名防篡改原理:
  服务器用只有自己知道的密钥,对 Header+Payload 的拼接字符串进行哈希签名
  客户端修改任何一段内容,重新计算的签名都会和原签名不一致
  服务器验证时,会用相同的密钥重新计算签名,对比是否匹配,不匹配直接拒绝

Token 与 Session-Cookie 核心区别

维度Token(JWT)Session-Cookie
存储位置 客户端(前端可控) 服务器(Session)+ 客户端(Cookie 存 SessionID)
状态 无状态(服务器不存会话) 有状态(服务器需维护 Session 表)
扩展性 极佳(分布式 / 微服务直接共享) 差(需 Session 共享 / 粘性会话)
跨域支持 天然支持(放在请求头) 受同源策略限制
CSRF 风险 低(不依赖 Cookie) 高(Cookie 自动携带)
XSS 风险 高(存在 localStorage 易被窃取) 低(HttpOnly Cookie 无法被 JS 读取)
主动注销 困难(需黑名单机制) 简单(直接删除服务器 Session)

2. Django操作Cookie

2.1 前言

虽然cookie是服务端发送给客户端浏览器需要的保存内容
但是客户端浏览器可以选择拒绝保存
如果禁止自动保存cookie
那么只要是需要登录的网站都没办法正常登录了

2.2 视图函数返回值

正常情况下返回的是对象

return HttpResponse()
return render()
return redirect()

不直接返回对象,先用变量名指代,返回变量名

obj1 = HttpResponse()
return obj1obj2 = render()
return obj2obj3 = redirect()
return obj3
想要操作cookie,必须进行以上变形才可以

2.3 操作cookie

[1] 设置cookie

obj = HttpResponse()
obj.set_cookie(key,value)
return obj

参数:

  key, 键
  value='', 值
  max_age=None, 超时时间,以秒为单位
  expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
  path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
  domain=None, Cookie生效的域名
  secure=False, https传输
  httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

[2] 获取cookie

request.COOKIES.get(key)

[3] 删除cookie

    obj = redirect('/app01/login/')obj.delete_cookie('sign')return obj

2.4 设置与获取cookie代码案例

[1] 登录功能--服务端向客户端发送cookie

项目的urls.py

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('app01/login/', views.login)
]

app01的views.py

def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':obj = HttpResponse('登录成功')obj.set_cookie('name1', 'avril1')return objreturn render(request, 'login.html')

app01的login.html

<body>
<form action="" method="post"><p>username: <input type="text" name="username"></p><input type="submit">
</form>
</body>

首次打开浏览器时cookie为空

image

输入用户名avril点击提交之后

image

[2] 只有登录才能查看home页面

项目的urls.py

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('app01/home/', views.home),path('app01/login/', views.login),
]

app01的views.py

def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':return redirect('/app01/home/')return render(request, 'login.html')def home(request):return HttpResponse('只有登录的用户才可以查看home页面')

app01的login.html

<body>
<form action="" method="post"><p>username: <input type="text" name="username"></p><input type="submit">
</form>
</body>

打开登录页面,输入用户名点击提交,跳转到home页面

image

image

直接访问home页面(没有登录直接访问)

image

[3] 解决不登录直接访问的问题

app01的views.py

def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':obj = redirect('/app01/home/')# 设置cookieobj.set_cookie('sign', 'abc123')return objreturn render(request, 'login.html')def home(request):# cookie正确则登录成功if request.COOKIES.get('sign') == 'abc123':return HttpResponse('用户已登录,当前是home页面')# cookie错误则跳转到登录页面return redirect('/app01/login/')

 直接访问/app01/home/时,跳转到/app01/login/

访问登录页面,输入用户名点击提交

image

image

[4] 多个视图函数需要添加登录认证

当多个视图函数都需要用到登录认证时,需要用到装饰器

项目的urls.py

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('app01/home/', views.home),path('app01/login/', views.login),path('app01/index/', views.index),path('app01/order/', views.order),
]

app01的views.py

from django.shortcuts import render, HttpResponse, redirect# Create your views here.def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':obj = redirect('/app01/home/')# 设置cookieobj.set_cookie('sign', 'abc123')return objreturn render(request, 'login.html')def login_auth(func):def inner(request, *args, **kwargs):if request.COOKIES.get('sign') == 'abc123':res = func(request, *args, **kwargs)return reselse:return redirect('/app01/login/')return inner@login_auth
def home(request):return HttpResponse('用户已登录,当前是home页面')@login_auth
def index(request):return HttpResponse('用户已登录,当前是index页面')@login_auth
def order(request):return HttpResponse('用户已登录,当前是order页面')

当直接访问app01/home/、app01/index/、app01/order/时,跳转到login页面

输入用户名avril点击提交之后,首先直接跳转到home页面,此时有了cookie

image

image

然后可以访问app01/index/、app01/order/

image

image

当直接访问app01/home/、app01/index/、app01/order/时,跳转到login页面,输入用户名登录之后统一跳转到home页面,无法跳转到index、order

[5] 解决跳转到login之后无法跳转到目的URL的问题

(1)前提知识

URL举例:http://localhost:8000/app01/login/?next={target_url}

  ? 是 HTTP URL 标准中查询字符串(Query String)的唯一分隔符,它将 URL 拆分为两部分:
  前面:http://localhost:8000/app01/login/ → 服务器要处理的资源路径(对应 Django 的 URLconf 路由)
  后面:next={target_url} → 传给该资源的GET 请求参数(键值对形式)
1、通用 HTTP 层面的作用
  传递额外的动态参数:多个参数用&连接,格式为?key1=value1&key2=value2
  影响服务器响应:服务器解析这些参数后,可返回差异化内容(比如分页?page=2、筛选?status=active)
  GET 请求专属:参数明文出现在 URL 中,长度有限制(浏览器 / 服务器通常限制 2KB 左右),不适合传敏感数据

2、Django 登录场景的作用
  next={target_url} 是 Django 内置登录系统的标准约定参数,也是最常用的查询参数用法
  功能:用户登录成功后,自动重定向到next指定的目标页面

? 之后的内容 不是 URL 的实际路径,仅作为查询参数(Query String)存在,用于向服务器传递额外的键值对数据。
服务器在进行路由匹配时只会解析 ? 之前的部分,? 之后的内容仅用于向该路径传递额外数据。

(2) 代码

app01的views.py

from django.shortcuts import render, HttpResponse, redirect# Create your views here.def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':# 在登录认证已经获取目的URL的基础上,再获取目的URL# next内容是GET请求参数里的键值对next_path = request.GET.get('next')# 跳转到目的URL next_path,而非之前的/app01/home/obj = redirect(next_path)# 设置cookieobj.set_cookie('sign', 'abc123')return objreturn render(request, 'login.html')def login_auth(func):def inner(request, *args, **kwargs):print(request.get_full_path())  # 获取用户登录之前的目的URLtarget_url = request.get_full_path()if request.COOKIES.get('sign') == 'abc123':res = func(request, *args, **kwargs)return reselse:# 将目的URL当作参数传给登录函数return redirect(f'/app01/login/?next={target_url}')return inner@login_auth
def home(request):return HttpResponse('用户已登录,当前是home页面')@login_auth
def index(request):return HttpResponse('用户已登录,当前是index页面')@login_auth
def order(request):return HttpResponse('用户已登录,当前是order页面')

访问http://localhost:8000/app01/index/,仍然访问/app01/login/,但是增加了查询参数next

image

输入用户名avril点击提交,跳转到index页面而非之前的home页面

image

当直接访问login页面,输入用户名并点击提交时,报错

image

image

login函数加上if next_path

def login(request):if request.method == 'POST':username = request.POST.get('username')if username == 'avril':# 在登录认证已经获取目的URL的基础上,再获取目的URL# next内容是GET请求参数里的键值对next_path = request.GET.get('next')# 用户有可能直接访问登录页面if next_path:obj = redirect(next_path)  # 跳转到目的URL next_path,而非之前的/app01/home/else:obj = redirect('/home/')  # 直接访问登录页面之后跳转到home页面# 设置cookieobj.set_cookie('sign', 'abc123')return objreturn render(request, 'login.html')

直接访问login页面,输入用户名点击提交,跳转到指定的home页面

image

 image

2.5 删除cookie代码案例

views.py中添加logout函数

@login_auth
def logout(request):obj = redirect('/app01/login/')obj.delete_cookie('sign')return obj

输入用户名avril,点击提交之后跳转到home页面,生成cookie

image

image

以上登录基础上访问logout,跳转到login页面,cookie被删除

image

3. django操作session

3.1 前言

session数据是保存在服务端的,给客户端返回的是一个加密后的字符串(sessionid)

# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()# 会话session的key
request.session.session_key# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")# 删除当前会话的所有Session数据  只删客户端
request.session.delete()# 删除当前的会话数据并删除会话的Cookie。 服务端、客户端都删
request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问例如,django.contrib.auth.logout() 函数中就会调用它。# 设置会话Session和Cookie的超时时间  默认过期时间是14天
request.session.set_expiry(value)* 如果value是个整数,session会在些秒数后失效。* 如果value是个datatime或timedelta,session就会在这个时间后失效。* 如果value是0,用户关闭浏览器session就会失效。* 如果value是None,session会依赖全局session失效策略。

必须先进行orm迁移,在数据库中自动生成django_session表

否则直接访问设置session的视图函数会报错

image

3.1 设置Session

[1] 语法

request.session['key'] = value

[2] 代码

项目的urls.py

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('app01/tool/', views.tool),
]

app01的views.py

def tool(request):request.session['sign1'] = 'abc666'return HttpResponse('设置session操作')

访问设置session的路由时,django_session数据库生成session_key、session_data,session_key以sessionid形式发送给客户端浏览器

image

image

3.2 获取Session

[1] 语法 

request.session.get('key')

[2] 原理

从请求 Cookie 中读取 sessionid
通过 session_key 查找未过期的数据库记录
数据解码,返回 Python 字典

[2] 代码

项目的urls.py

from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path('app01/tool/', views.tool),path('app01/get_sign/', views.get_sign)
]

app01的views.py

def tool(request):request.session['sign1'] = 'abc666'return HttpResponse('设置session操作')def get_sign(request):res = request.session.get('sign1')print(res)return HttpResponse('获取session操作')

image

获取session时,后端打印的是实际的session值,而非加密后的字符串

image

3.3 设置、获取多个session

app01的views.py

def tool(request):request.session['sign1'] = 'abc666'request.session['sign2'] = 'abc999'request.session['sign3'] = 'abc123'return HttpResponse('设置session操作')def get_sign(request):res = request.session.get('sign1')res2 = request.session.get('sign2')res3 = request.session.get('sign3')print(res, res2, res3)return HttpResponse('获取session操作')

先访问设置页面

image

image

再访问获取页面

image

image

结论:

给session设置多个值的时候,存在数据库中的数据仍是一条
但是在取session的时候,可以通过request.session对象获取到设置的多组键值对

3.4 session配置

django提供了5种类型的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,默认修改之后才保存(默认)

 

http://www.jsqmd.com/news/970546/

相关文章:

  • 广州老房翻新多少钱?2026年各项目费用明细+避坑指南+公司推荐 - 优家闲谈
  • 传统老年人必须静养,编写程序根据心肺功能,肢体数据,判定老人适宜活动量,破除静养误区。
  • 2026降AIGC软件实测:10款工具对比,论文质量提升秘籍
  • Windows任务栏透明化神器:3分钟让你的桌面焕然一新!
  • 书匠策AI官网www.shujiangce.com:你的期刊论文搭子,比导师还“懂行“
  • 安顺母婴除甲醛CMA甲醛检测治理公司深度测评:绿呼吸环保稳居榜首 - 一修哥咨询
  • 跟着 MDN 学JavaScript day_7:数学运算与逻辑判断实战测试
  • 【飞机】基于matlab固定翼飞机动力学与控制【含Matlab源码 15601期】
  • SteamAutoCrack:终极游戏DRM破解工具使用完全指南
  • 沧州母婴除甲醛CMA甲醛检测治理公司深度测评:绿呼吸环保稳居榜首 - 一修哥咨询
  • 成都装修公司哪家好?2026年主流公司报价对比+怎么选 - 优家闲谈
  • 保姆级教程:手把手教你用Spring Boot集成农行openbank-sdk-java完成H5电子账户开户
  • 8分钟极速上手:用AI智能分层工具彻底告别手动抠图烦恼
  • EdB Prepare Carefully:从随机开局到精准定制的RimWorld角色管理解决方案
  • 别再死磕公式了!用Python实战模拟TDOA定位(从Chan到Fang算法对比)
  • 5分钟快速掌握:NcmpGui免费极速NCM音乐转换终极方案
  • 2026 数学新高考一卷 19 题(不会做)
  • VB6 IDE里调Cdecl DLL不再崩溃:调试+编译双通的运行时补丁工具
  • 【20年平台生态专家亲测】CSDN AI营销套餐到期后,已发文章SEO权重保留多久?3组A/B测试数据揭晓
  • 昌邑母婴除甲醛CMA甲醛检测治理公司深度测评:绿呼吸环保稳居榜首 - 一修哥咨询
  • 索尼相机隐藏功能解锁终极指南:如何快速解除30分钟录制限制
  • 区间本质不同子串数 题解
  • 摆脱论文困扰!!2026 最新降AI率网站测评与推荐
  • 安丘母婴除甲醛CMA甲醛检测治理公司深度测评:绿呼吸环保稳居榜首 - 一修哥咨询
  • Windows端口转发管理终极指南:如何用PortProxyGUI告别复杂命令
  • 3个关键步骤解锁Balena Etcher:跨平台系统镜像烧录新体验
  • 别只盯着SCI:如何高效搞定一次IEEE会议投稿(以CAC为例,含审稿状态解读与超页费避雷)
  • 【限时解密】CSDN AI数字营销套餐节假日定价逻辑:3大算法因子+2个决策节点,90%用户不知道的议价时机
  • 2026年6月不锈钢波纹管供应商哪家强,穿线软管/金属软管/电暖器/电热管/不锈钢波纹管,不锈钢波纹管工厂哪个好 - 品牌推荐师
  • TegraRcmGUI:3分钟学会Switch RCM注入的Windows图形化工具