0

0

Flask set_cookie 失效问题解析与正确实践

花韻仙語

花韻仙語

发布时间:2025-09-14 11:43:19

|

641人浏览过

|

来源于php中文网

原创

Flask set_cookie 失效问题解析与正确实践

本文深入探讨Flask应用中set_cookie无法正确设置cookie的常见原因。核心问题在于未返回包含cookie的make_response对象,而是直接返回了jsonify结果。教程将提供正确的实现方式,并强调跨域(CORS)配置的重要性,确保cookie能被客户端正确接收和存储。

理解Flask的响应与Cookie设置机制

在flask应用中,当我们需要设置http响应头(例如设置cookie)时,不能仅仅依赖于直接返回一个json对象。flask的jsonify函数会创建一个response对象,其默认行为是返回json数据,但它不会自动包含之前在另一个response对象上设置的任何http头。

问题的核心在于,开发者创建了一个make_response对象并使用response.set_cookie()方法在其上设置了accessToken。然而,最终返回的却是jsonify(mensagem),这创建了一个全新的响应对象,而原先设置了cookie的response对象却被丢弃了,导致cookie信息未能随HTTP响应发送到客户端。

原始的错误代码示例:

# user.py (错误实现)
from flask import jsonify, make_response
import jwt # 假设已导入并配置SECRET_KEY

def loginAccount():
    # ... 用户认证逻辑 ...
    userId = str(list(db['users'].find({"email": email}))[0]['_id']) # 假设db和email已定义
    tokenId = jwt.encode({'userId': userId}, SECRET_KEY, algorithm='HS256')

    mensagem = {'message': f'Welcome to the CharTwo {email}!', 'tokenId': tokenId}

    # 创建一个响应对象并设置cookie
    response = make_response(jsonify(mensagem)) # 注意这里jsonify先被调用,创建了响应体
    response.set_cookie('accessToken', tokenId)

    # 错误:返回了一个新的jsonify结果,而不是包含cookie的response对象
    return jsonify(mensagem)

在上述代码中,response = make_response(jsonify(mensagem)) 这一行首先通过 jsonify(mensagem) 创建了一个响应体,然后 make_response 将其封装成一个可操作的 Response 对象。接着 response.set_cookie('accessToken', tokenId) 在这个 Response 对象上添加了 Set-Cookie 头。然而,随后的 return jsonify(mensagem) 却又创建了一个全新的、不包含之前设置的 Set-Cookie 头的 Response 对象并将其返回。这导致客户端接收到的响应中没有 accessToken 这个cookie。

正确设置Cookie的实现

要确保set_cookie()生效,必须返回那个经过set_cookie()操作的Response对象。

正确的loginAccount函数实现:

# user.py (正确实现)
from flask import jsonify, make_response
import jwt # 假设已导入并配置SECRET_KEY

def loginAccount():
    # ... 用户认证逻辑 ...
    # 假设db['users'].find({"email": email}) 成功找到用户
    # 假设email和SECRET_KEY已在作用域内定义
    userId = str(list(db['users'].find({"email": email}))[0]['_id'])
    tokenId = jwt.encode({'userId': userId}, SECRET_KEY, algorithm='HS256')

    mensagem = {'message': f'Welcome to the CharTwo {email}!', 'tokenId': tokenId}

    # 首先创建包含JSON数据的响应对象
    # make_response 可以接受字符串、字典、元组或Response对象作为参数
    # 如果直接传入字典,Flask会将其自动转换为JSON响应
    response = make_response(jsonify(mensagem))

    # 在这个响应对象上设置cookie
    response.set_cookie('accessToken', tokenId, httponly=True, secure=True, samesite='Lax') # 推荐添加httponly, secure, samesite等属性

    # 返回包含cookie的响应对象
    return response

在这个修正后的版本中,response对象被正确创建并设置了cookie,最终也是这个response对象被返回。这样,Set-Cookie头就会包含在HTTP响应中,客户端浏览器就能接收并存储该cookie。

彩葫芦
彩葫芦

用AI生成故事漫画、科普绘本、小说插画,加入彩葫芦绘画社区,一起释放创造力!

下载

注意事项:

  • httponly=True: 推荐将此属性设置为True,防止客户端脚本(如JavaScript)访问cookie,增加安全性,减少XSS攻击的风险。
  • secure=True: 如果您的应用通过HTTPS提供服务,应将此属性设置为True,确保cookie只通过加密连接发送。
  • samesite='Lax' 或 'Strict': 用于防止CSRF攻击。Lax是较宽松的默认值,允许顶级导航和GET请求发送cookie;Strict则更严格,只在同站请求时发送cookie。根据您的安全需求选择。
  • expires 或 max_age: 可以设置cookie的有效期。如果不设置,cookie将是会话cookie,浏览器关闭后即失效。

跨域(CORS)与Cookie处理

在前后端分离的架构中,尤其当前端(如VueJS)和后端(如Flask)部署在不同的域名或端口时,处理跨域请求是必不可少的。为了让客户端能够发送和接收带有凭证(如Cookie)的跨域请求,需要进行以下配置:

  1. 客户端(Axios)配置: 在发起请求时,必须设置withCredentials: true。这会指示浏览器在跨域请求中包含cookie和其他授权头。

    const apiUrl = 'http://127.0.0.1:5000'
    
    axios
      .post(
        `${apiUrl}/api/account/login`,
        {
          email: this.email,
          password: this.password,
        },
        {
          withCredentials: true, // 关键:允许发送和接收跨域凭证(包括cookie)
        }
      )
      .then((response) => {
        alert(response.data.message);
        console.log(response);
      })
      .catch((error) => {
        alert(`${error.response.data.erro}`);
        console.log(error);
      });
  2. 服务器端(Flask-CORS)配置: Flask后端需要配置flask_cors扩展,以允许来自特定源的跨域请求携带凭证。

    # main.py
    from flask import Flask, make_response
    from flask_cors import CORS, cross_origin
    from user import loginAccount # 假设loginAccount已导入
    
    app = Flask(__name__)
    CORS(app, supports_credentials=True, origins=["http://localhost:8080", "http://127.0.0.1:8080"]) # 明确指定允许的源,并开启凭证支持
    
    @app.route('/')
    def principal():
        return 'Welcome to the CharTwo API.'
    
    @app.route('/api/account/login', methods=['POST'])
    @cross_origin(supports_credentials=True) # 针对特定路由也开启凭证支持
    def login_account():
        return loginAccount()
    
    if __name__ == '__main__':
        app.run(debug=True)

    CORS(app, supports_credentials=True, origins=["http://localhost:8080"]):

    • supports_credentials=True:这是允许浏览器发送和接收带有凭证(如Cookie)的跨域请求的关键。当此选项为True时,Access-Control-Allow-Credentials响应头将被设置为true。
    • origins=["http://localhost:8080"]:明确指定允许访问API的客户端源。不推荐使用*作为origins,因为它可能带来安全风险。

    @cross_origin(supports_credentials=True): 虽然在CORS(app, ...)中已经全局配置了supports_credentials=True,但在特定路由上再次使用@cross_origin装饰器并设置supports_credentials=True,可以进一步确保该路由的CORS行为符合预期,尤其是在更复杂的CORS策略中。

总结

在Flask应用中正确设置HTTP Cookie的关键在于:

  1. 使用make_response()创建可操作的响应对象:在需要修改响应头(如设置Cookie)时,务必通过make_response()获取一个Response对象。
  2. 在正确的响应对象上调用set_cookie():确保set_cookie()方法是在您打算返回给客户端的那个Response对象上调用的。
  3. 返回包含Cookie的Response对象:最终,必须返回经过set_cookie()操作后的Response对象,而不是一个新创建的、不含Cookie信息的响应。
  4. 配置CORS以支持凭证:对于跨域请求,客户端(如Axios的withCredentials: true)和服务器端(如flask_cors的supports_credentials=True和明确的origins)都必须正确配置,才能确保Cookie能够被发送和接收。

遵循这些原则,可以有效避免Flask中Cookie设置不生效的问题,并确保应用在安全和功能上都表现良好。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

544

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

372

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

727

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

470

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

393

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

990

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

655

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

544

2023.09.20

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

148

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 5.8万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号