背景
項(xiàng)目使用了nginx作為反向代理队丝,從外部瀏覽器獲取到https再反向代理到本地的http乾胶。錯(cuò)誤配置文件如下
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('用戶名或密碼錯(cuò)誤')
return redirect(url_for('.login'))
部署上線后预愤,使用https訪問,登錄后藏杖,地址被跳轉(zhuǎn)到http://bbs.u14e.xyz
懂盐,由于沒有配80端口竭恬,所以這種情況會(huì)直接報(bào)錯(cuò)
原因
因?yàn)樯厦媾渲昧藥讉€(gè)proxy_set_header
用來獲取客戶真實(shí)IP,使得flask redirect
重定向的時(shí)候直接使用本機(jī)的協(xié)議熬的,瀏覽器控制臺(tái)查看響應(yīng)頭會(huì)看到Location: http://127.0.0.1:5000
(還是不要?jiǎng)hproxy_set_header
這些配置)
嘗試一
給nginx
添加80端口痊硕,使得redirect
轉(zhuǎn)到http
后,nginx再將http
轉(zhuǎn)到https
押框,443端口就可以將https
轉(zhuǎn)給本機(jī)的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:這樣轉(zhuǎn)來轉(zhuǎn)去的顯然很糟糕。當(dāng)然最后還是要加上80端口的重定向的
嘗試二:
使用url_for
:
return redirect(url_for('topic.index', _scheme="https", _external=True))
不過這樣的話橡伞,之前的代碼都要改一遍盒揉,而且開發(fā)環(huán)境不用https啊,還得手動(dòng)切換兑徘,多麻煩案沼!當(dāng)然可以封裝一下url_for
挂脑,判斷開發(fā)和生產(chǎn)環(huán)境藕漱,但是感覺還是太麻煩了。
嘗試三:
參考:http://flask.pocoo.org/snippets/35/ 寫個(gè)中間件崭闲,看了時(shí)間谴分,年代久遠(yuǎn),還是不試了镀脂。
終極方案
nginx
配置文件添加牺蹄,指定協(xié)議,參考: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生產(chǎn)環(huán)境 從https到http跳轉(zhuǎn)
}
}