Flask渲染模板时自定义Session类初始化异常,不同设备返回相同数据
第一步:补全缺失的依赖导入
你当前给出的导入代码中没有引入Flask的请求上下文对象request,如果实际运行代码也未导入,会出现两种异常情况:
- 全局作用域提前导入并错误初始化了
request相关值,导致所有请求复用首次初始化的固定IP、用户信息 - 直接抛出未定义变量的运行错误
修复方法:在导入语句中补充request引入:
from flask import Flask, render_template, session, request
第二步:排查反向代理IP传递问题
如果你的Flask服务前置了Nginx、Apache等反向代理服务,默认配置下request.remote_addr获取到的是代理服务的本地地址(比如127.0.0.1),所有请求的IP都会显示为同一个值。
排查方法:在路由函数中添加日志打印request.remote_addr的值,检查不同设备访问时的输出是否一致:
@app.route('/', methods=['GET'], strict_slashes=False) def indexpage(): print("当前请求IP:", request.remote_addr) return render_template('index.html',s=Session())
如果打印的IP均为本地回环地址,修复反向代理配置即可,以Nginx为例,需要在location配置块中添加如下参数:
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
之后在Flask中使用request.headers.get("X-Real-IP")获取真实客户端IP即可。
另外request.remote_user默认返回空值,只有你的服务配置了HTTP基础认证时才会返回对应用户名,如果所有请求的name属性都为空属于正常情况,可以自行替换为其他自定义的用户属性。
第三步:检查是否存在全局实例化错误
确认你的Session类实例化操作完全在路由函数内部执行,不要在全局作用域提前实例化Session对象:全局变量只会在服务启动时初始化一次,会复用首次生成的属性值,导致所有请求返回相同结果。
第四步:验证session存储逻辑
Flask默认的session存储在客户端cookie中,如果你测试时不同设备使用了相同的cookie信息,也会读取到相同的session值,可以清理浏览器cookie或者用无痕模式测试确认。
修复后可以在模板中同时打印request.remote_addr和s.ip的值,确认两者一致即可。
内容的提问来源于stack exchange,提问作者Shevon Kwan

