Flask03——cookie和session

本文深入讲解了Cookie和Session的工作原理及在Flask框架中的应用,包括它们如何解决HTTP无状态问题,实现用户身份验证和状态保持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cookie技术的必要性

今天来讲一个在现今web应用中,最最基础和最最重要的技术点,几乎没有他们就无法促成web技术的推广和应用,他们就是cookie和session一对孪生兄弟。先说一下他们诞生和存在的必要性。
我们在浏览网站的时候,访问每一个页面都需要使用“http协议”来实现。而http协议是无状态的协议,就是说http协议没有一个内部的机制来维护两次请求之间的状态保持。比如说当一个用户请求同一个网站的A页面后,再请求B页面,http协议不能告诉服务器这两次请求是来自于同一个用户。而是会把两次请求当做独立的请求。而要让网站能记住多次请求来自同一个用户的这种需求在网站开发中是非常必需的技术。下面举一个我们经常用到的网站的功能你就能明白为什么需要这种技术了。
比如我们在网上购物的时候,往往会添加多个商品到自己的购物车当中,每添加一件商品就是一次请求,那么为了使得我们多次添加购物车的动作都能放到同一个用户的名下,是不是需要保证多个请求的请求来自于同一个用户?所以对这一技术的强烈需求就诞生了cookie技术。

cookie的实现原理

cookie可以将用户信息比如用户id保存到浏览器当中的cookie里面,cookie是一个类似缓存的东西,当用户通过验证之后服务器就会将用户的id保存到cookie里面,当用户请求不同页面的时候都会携带着用户的id,如果进行添加购物车的动作的话,那么多个商品都会放到此用户id下面,当用户需要下单的时候程序就会通过此id对应找到数据库里面的此用户的记录,生成一条此用户id的订单记录。这样就能实现不同页面跳转的时候唯一确定用户身份了。

打个比较容易理解的比喻:如果把服务器比作一家商场,商场中的每个店面比做一个页面,而cookie好比你第一次去商场时,经过你提供用户信息之后,由商场为你提供的一张会员卡。当你在这家商场的任何店面中购物时,只要你提供由你保存的会员卡,就会被看做商场的会员。你在此商城所有店面所购买的所有商品都会放到你的会员名下。
cookie原理示意图:
在这里插入图片描述

flask是如何实现和应用cookie技术的

首先肯定是保存cookie,保存cookie这个动作一般是用在登录的时候,那么下面就让我们写一个模拟登录的视图函数login,由于现在还不涉及和数据库的验证交互,所以就不进行验证,就算验证通过了,然后直接写入cookie

# 顶部引入make_response
from flask import Flask, make_response


@app.route('/login')
def login():
    response = make_response('登录成功!')  # 实例化响应对象
    response.set_cookie('username', 'xiaoming')  # 通过相应对象的set_cookie方法设置cookie,
    # cookie信息是一个键值对形式的数据,以cookie形式进行保存
    return response

这里需要用到相应对象make_response,实例化之后,可以用它的一个方法set_cookie进行cookie信息的保存。保存之后返回响应结果。如果我们请求这个视图函数之后,键值对形式的username=xiaoming就被保存到了cookie当中了。我们可以通过检查元素的存储,再点击cookie查看保存的cookie信息。如果正常保存就可以看到保存的cookie信息。这样保存用户信息之后,当我们再次通过浏览器发起对服务器的请求的时候,浏览器就会自动带上此网站的cookie,由于cookie中保存的是用户信息,所以我们就可以以此来唯一确定用户身份了。就可以保持状态了。
登录之后,我们下一步就要验证看看我们是否可以从cookie当中拿到保存在cookie中的用户信息呢?如果能拿到,那么我们就可以进行展示出来,也就是我们经常在网站右上角看到的,登录之后显示的用户名等个人信息。那么下面我们再来创建一个登录信息的视图函数。

@app.route('/user_info')
def user_info():
    return request.cookies.get('username', '用户信息不存在!')

以上代码就是通过上一节我们用到的request对象下面的cookies来拿到cookie当中保存的用户信息,如果找不到用户信息,则提示用户信息不存在。
现在已经模拟了登录和访问用户中心了,接下来就该退出了。退出的语法应该这样来写。

@app.route('/logout')
def logout():
    response = make_response('退出成功!')
    response.delete_cookie('username')
    return response

这次依然用到了make_response对象的删除cookie的方法来清除cookie记录。cookie一旦被清除,那么在用户中心就获取不到用户信息了,就会输出用户信息不存在!

session的实现原理

sesion和cookie相似,都是用来存储用户信息的,最大的不同在于,cookie是将用户信息保存在客户端的计算机中,而session则是将用户的信息加密以后放到服务器的session当中,由于服务器上会保存很多用户的信息,所以要对各自的session信息进行编号,就类似在服务器放了很多盒子,每个盒子里面存放着一个用户的加密信息,那么每个盒子的编号我们这里用session_id来表示,服务器就会把这个session_id返回到客户端,客户端把这个session_id保存到cookie当中,下次再请求服务器的时候,会自动带上这个session_id由于每个人的session_id都是随机生成,而且是唯一的,所以就能唯一确定用户身份。还有就是,用户信息这次是加密之后保存在服务器端的,所以要比cookie更加安全。
对比我们在cookie中举得例子,可以这样来形容:如果用户去商场的时候忘记带会员卡了,但是他之需要提供卡号(session_id)就还是可以唯一确定用户身份的,因为会员卡号肯定是唯一的。
session实现原理示意图:
在这里插入图片描述

flask的session原理

上面讲的时常规的session原理,而flask框架在上面的基础之上,又做了一次封装,使得我们读取和使用session更加简单。flask是直接将加密之后的用户数据返回给了客户端,客户端再通过cookie进行保存,所以依然是让客户端保存用户信息,而不是返回盒子编码(session_id),这样,服务器就不用保持用户信息了,节省了服务器的开销。那么取session当中的用户信息也是可以直接取,就不用再经过session_id这个中间环节了。由于我们一直在强调是要把用户信息加密之后进行保存的,所以就需要设置一个SECRET_KEY,这个就相当于对我们的加密算法加盐,也就是加了我们自定义的干扰项,更进一步的保证数据的安全性。
由于flask这种封装,所以我们在操作session的时候就相当于操作session这个字典一样,所以关于登录、用户中心,退出这些功能的实现一并展示到下面统一为大家做解释。

@app.route('/login2')
def login2():
    session['username'] = 'xiaohua'
    return '登录成功!'


@app.route('/user_info2')
def user_info2():
    return session.get('username', '用户信息不存在!')


@app.route('/logout2')
def logout2():
    session.pop('username', None) # None参数保证不报错,也就是当pop找不到需要删除的下标的时候会返回None,从而使得不报错。
    return '退出成功!'

flask实现session原理示意图:
在这里插入图片描述
对于登录就是往session字典当中加元素就可以了,加了之后就可以通过下标访问到用户的信息在用户中心进行展示输出,那么退出登录的时候可以通过键找到相应的键值对,一并弹出删除,如果不存在返回None,避免报错。

### 浏览器不生成Cookie的原因及解决方案 #### 原因分析 1. **浏览器设置** 用户可能已经禁用了浏览器中的Cookie功能。现代浏览器允许用户自定义隐私选项,其中包括完全阻止第三方或所有类型的Cookies[^1]。 2. **同源政策(Same-Origin Policy)** 如果网页尝试设置跨域的Cookie,则会受到浏览器的安全机制限制而不予保存。这种情况下,只有当请求来自同一域名下的资源时才会成功创建并发送Cookie给服务器。 3. **HTTP头部配置错误** 当响应头`Set-Cookie`字段存在语法问题或是缺少必要的属性(比如路径、有效期等),也可能导致客户端无法正常解析进而拒绝接受该Cookie。 4. **Do Not Track (DNT) 请求** 若用户的浏览器启用了“勿跟踪”模式,并且站点尊重此信号,则可能会抑制某些形式的数据收集行为,包括但不限于Cookie写入操作。 5. **扩展程序干扰** 部分广告拦截器或其他安全增强型插件也会主动过滤掉特定来源设定的新Cookie项,从而影响到预期的功能逻辑执行效果。 6. **无痕浏览模式(InPrivate/Incognito Mode)** 处于隐身窗口状态下打开页面,默认不会持久化任何新的Session Storage记录以及临时文件夹内的缓存条目,这同样适用于新产生的Cookie实例。 7. **Flash Cookie 影响** 虽然主要讨论的是传统意义上的HttpOnly Cookies,但是考虑到一些老旧平台仍然依赖Adobe Flash Player技术栈,在极少数场景下,如果系统内残留着旧版本播放控件并且其内部维护了一套独立于标准Web API之外的状态管理机制的话,那么这些遗留因素或许会对整体环境造成间接性的阻碍作用[^2]。 8. **浏览器指纹识别冲突** 某些高级别的自动化工具能够基于多维度特征组合构建独一无二的身份标识符——即所谓的“浏览器指纹”。一旦此类算法判定当前访问实体具有高度相似度甚至重复出现的情况,出于保护目的便有可能采取措施防止进一步关联敏感数据交换过程,其中就包含了对新建Cookie指令的有效性验证环节[^4]。 9. **XSS攻击防护机制触发** 为了防范潜在的安全风险,许多主流框架集成了自动化的输入校验流程,它们会在渲染前先扫描待处理的内容片段是否存在可疑脚本注入迹象。倘若检测到了异常活动,则不仅会使相应部分失效,还可能导致整个事务回滚至初始状态,自然也就谈不上后续有关个性化偏好参数传递事宜了[^3]。 #### 解决方案建议 针对上述提到的各种可能性,可以考虑如下几种应对策略: - 对于由**浏览器设置**引起的问题,应当指导最终使用者前往相关界面调整权限级别直至满足业务需求为止; - 关于**同源原则**所造成的障碍,开发人员需确保前后端交互遵循严格的协议规定,必要时可通过CORS(跨资源共享)声明放宽约束条件; - 就**HTTP头部格式不当**而言,务必仔细审查服务端返回包结构,参照RFC文档修正存在的缺陷之处; - 如遇**DNT标志位生效**的情形,除非绝对必需,一般推荐绕过这类限制继续提供基础级的服务体验而非强制改变现状; - 至于那些受制于**附加组件规则**的对象,要么劝说客户卸载不必要的软件产品,要么寻找兼容性更好的替代品; - 在涉及**私密空间**的操作里边,除了提醒人们注意区分不同应用场景外,也可以探索其他更灵活的方式来维持连续性一致性; - 鉴于**Flash Cookie**方面的影响日益减小,现阶段更多关注如何平稳过渡到HTML5及以上规格的技术路线即可; - 面临**浏览器指纹匹配失败**带来的挑战,一方面要持续优化前端代码质量减少误判概率,另一方面则积极寻求官方支持获取最新版SDK更新; - 最后对于疑似遭遇**CSRF/XSRF防御体系激活**事件的发生,应该深入排查具体原因所在,同时强化自身的编码习惯养成良好实践范式。 ```javascript // 设置cookie示例 document.cookie = "username=John Doe; path=/"; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值