Nginx反向代理Gunicorn部署Flask应用时Session为空问题
Flask通过Gunicorn+Nginx反向代理部署后Session失效问题排查与解决
当Flask应用通过Gunicorn部署在Nginx反向代理后,出现Session无法正常工作的问题——每次请求的session对象均为空,登录后跳转/admin接口会被302重定向回登录页,核心原因是@login_required装饰器校验Flask的SecureSessionCookie时发现其为空。
相关配置与代码
Nginx配置
server { listen 443 ssl http2; listen [::]:443 ssl http2; ssl_certificate /etc/ssl/cert.pem; ssl_certificate_key /etc/ssl/key.pem; server_name www.kanser.online; proxy_headers_hash_max_size 1024; proxy_headers_hash_bucket_size 128; location / { include proxy_params; proxy_pass http://unix:/root/hsctech/hsctech.sock; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Prefix /; proxy_set_header Cookie $http_cookie; proxy_cookie_path / /; } }
Flask登录相关代码(基于flask-login)
登录接口
@auth_view.route("/login", methods=["GET", "POST"]) def login(): form = LoginForm(request.form) if request.method == "POST" and form.validate(): if authenticate_user(form.username.data, form.password.data): flash("Logged in successfully.", "success") return redirect(location=url_for("views.admin.admin")) else: flash("Invalid username or password.", "error") try: return render_template("login.html", form=form) except TemplateNotFound: abort(404) except TemplateSyntaxError: abort(500)
登录后跳转的/admin接口
@admin_view.route("/admin") @login_required def admin(): try: return render_template("admin.html") except TemplateNotFound: abort(404) except TemplateSyntaxError: abort(500)
Gunicorn systemctl配置
[Unit] Description=Gunicorn instance to serve Flask After=network.target [Service] User=root Group=www-data WorkingDirectory=/root/hsctech Environment="PATH=/root/hsctech/.venv/bin" ExecStart=/root/hsctech/.venv/bin/gunicorn --workers 3 --bind unix:hsctec.sock -m 007 wsgi:app
问题现象
请求流程:GET /login打开登录页 → POST /login提交表单 → GET /ADMIN被302重定向回登录页。核心原因是@login_required校验时,SecureSessionCookie为空,Session未被正确传递或识别。
解决方案
1. 修复Gunicorn与Nginx的Sock文件拼写错误
Gunicorn配置中绑定的sock文件名为hsctec.sock,但Nginx代理指向的是hsctech.sock,拼写不一致会导致Nginx无法连接Gunicorn,请求无法正常转发,直接引发Session失效问题。
修正Gunicorn的ExecStart行:
ExecStart=/root/hsctech/.venv/bin/gunicorn --workers 3 --bind unix:hsctech.sock -m 007 wsgi:app
2. 补全Flask-Login的Session创建逻辑
当前登录接口仅验证用户身份,但未调用login_user()方法创建用户Session,这是登录后Session为空的直接原因。修改登录接口代码:
@auth_view.route("/login", methods=["GET", "POST"]) def login(): form = LoginForm(request.form) if request.method == "POST" and form.validate(): # 修改authenticate_user使其返回验证通过的用户对象 user = authenticate_user(form.username.data, form.password.data) if user: login_user(user) # 关键:调用login_user初始化用户Session flash("Logged in successfully.", "success") return redirect(location=url_for("views.admin.admin")) else: flash("Invalid username or password.", "error") try: return render_template("login.html", form=form) except TemplateNotFound: abort(404) except TemplateSyntaxError: abort(500)
3. 配置Flask信任反向代理
Flask需要明确识别反向代理环境,才能正确处理HTTPS下的Session Cookie属性。在Flask应用中添加以下配置:
app = Flask(__name__) # 信任本地反向代理(根据Nginx所在IP调整) app.config['TRUSTED_PROXIES'] = ['127.0.0.1'] # 强制使用HTTPS作为URL Scheme app.config['PREFERRED_URL_SCHEME'] = 'https' # 配置Session Cookie的安全属性 app.config['SESSION_COOKIE_SECURE'] = True app.config['SESSION_COOKIE_HTTPONLY'] = True app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
4. 优化Nginx代理配置(可选)
检查proxy_params文件是否已包含X-Forwarded-*相关头,避免重复设置导致冲突。若需明确Cookie传递规则,可添加:
proxy_cookie_domain $host $host;
关键总结
- 拼写错误:Gunicorn与Nginx的sock文件名不一致,导致请求转发失败。
- 缺失Session初始化:未调用
login_user()创建用户Session,这是登录后校验失败的核心原因。 - 反向代理信任配置:Flask需明确信任反向代理,才能正确处理HTTPS环境下的Session Cookie安全属性。
内容的提问来源于stack exchange,提问作者giraycoskun
相关产品推荐
相关产品推荐

