背景
项目使用了nginx作为反向代理,从外部浏览器获取到https再反向代理到本地的http。错误配置文件如下
server {
listen 443 ssl;
# 启用ssl
ssl on;
server_name bbs.u14e.xyz;
# 证书和私钥的地址
ssl_certificate /var/www/u-bbs/u14exyz/full_chain.pem;
ssl_certificate_key /var/www/u-bbs/u14exyz/private.key;
location /images {
alias /var/www/u-bbs/app/images;
}
location /static {
alias /var/www/u-bbs/app/static;
}
location / {
proxy_pass http://127.0.0.1:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
flask redirect
代码如下:用户登录成功后重定向到首页
@bp.route('/login', methods=['POST'])
@csrf_required
def login_post():
form = request.form
u = User.validate_login(form.to_dict())
if u is not None:
session['user_id'] = u.id
session.permanent = True
return redirect('/')
else:
flash('用户名或密码错误')
return redirect(url_for('.login'))
部署上线后,使用https访问,登录后,地址被跳转到http://bbs.u14e.xyz
,由于没有配80端口,所以这种情况会直接报错
原因
因为上面配置了几个proxy_set_header
用来获取客户真实IP,使得flask redirect
重定向的时候直接使用本机的协议,浏览器控制台查看响应头会看到Location: http://127.0.0.1:5000
(还是不要删proxy_set_header
这些配置)
尝试一
给nginx
添加80端口,使得redirect
转到http
后,nginx再将http
转到https
,443端口就可以将https
转给本机的http
了,如图:登录成功流程
server {
listen 80;
server_name bbs.u14e.xyz;
location / {
# redirect any requests to the same URL but on https
return 301 https://$host$request_uri;
}
}
PS:这样转来转去的显然很糟糕。当然最后还是要加上80端口的重定向的
尝试二:
使用url_for
:
return redirect(url_for('topic.index', _scheme="https", _external=True))
不过这样的话,之前的代码都要改一遍,而且开发环境不用https啊,还得手动切换,多麻烦啊!当然可以封装一下url_for
,判断开发和生产环境,但是感觉还是太麻烦了。
尝试三:
参考:http://flask.pocoo.org/snippets/35/ 写个中间件,看了时间,年代久远,还是不试了。
终极方案
nginx
配置文件添加,指定协议,参考:http://flask.pocoo.org/docs/1.0/deploying/wsgi-standalone/#proxy-setups
proxy_set_header X-Forwarded-Proto $scheme;
然后就可以了,可以了,可以了,是不是so easy~~~哈哈哈,只需要改一下nginx配置
最后附上nginx配置完整版
server {
listen 80;
server_name bbs.u14e.xyz;
location / {
# redirect any requests to the same URL but on https
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
# 启用ssl
ssl on;
server_name bbs.u14e.xyz;
# 证书和私钥的地址
ssl_certificate /var/www/u-bbs/u14exyz/full_chain.pem;
ssl_certificate_key /var/www/u-bbs/u14exyz/private.key;
location /images {
alias /var/www/u-bbs/app/images;
}
location /static {
alias /var/www/u-bbs/app/static;
}
location / {
proxy_pass http://127.0.0.1:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # fix flask redirect生产环境 从https到http跳转
}
}