AWS EC2上HTTPS域名对接HTTP Flask API的ERR_SSL_PROTOCOL_ERROR解决求助
你的猜测完全正确,这个错误就是HTTPS页面加载HTTP资源触发了浏览器的混合内容安全策略导致的——浏览器为了安全,不允许加密的HTTPS页面请求未加密的HTTP资源,直接拦截了你的API调用。下面给你几个从测试到生产的解决方案,步骤都很详细:
方案一:给Flask API配置HTTPS(彻底解决,推荐)
让API也用HTTPS提供服务,和Web应用保持一致:
获取SSL证书:用免费的Let's Encrypt证书就行
- 如果你用的是Ubuntu/Debian系统,先安装certbot:
sudo apt update && sudo apt install certbot - 生成证书(执行前先停掉占用80端口的服务,比如Web应用):
sudo certbot certonly --standalone -d abc.abc
证书会存在
/etc/letsencrypt/live/abc.abc/目录下,记住这个路径。- 如果你用的是Ubuntu/Debian系统,先安装certbot:
让Flask API使用HTTPS启动:
- 测试环境可以直接用Flask内置服务器(生产别用这个):
flask run --ssl-cert=/etc/letsencrypt/live/abc.abc/fullchain.pem --ssl-key=/etc/letsencrypt/live/abc.abc/privkey.pem --host=0.0.0.0 - 生产环境推荐用Gunicorn(先安装
pip install gunicorn):gunicorn --workers=4 --bind 0.0.0.0:443 --certfile=/etc/letsencrypt/live/abc.abc/fullchain.pem --keyfile=/etc/letsencrypt/live/abc.abc/privkey.pem app:app
这里的
app:app是你的Flask应用入口(第一个app是文件名,第二个是Flask实例名)。- 测试环境可以直接用Flask内置服务器(生产别用这个):
开放EC2安全组端口:在AWS控制台给EC2实例的安全组添加443端口的入站规则,允许所有IP访问。
之后Web应用调用https://abc.abc的API就不会报错了。
方案二:用Nginx做反向代理(生产环境最优解)
通过Nginx统一处理HTTPS请求,内部Web应用和API还是用HTTP,但外部访问全是HTTPS,这样不用改太多应用代码:
安装Nginx:
sudo apt install nginx配置Nginx站点:
创建配置文件/etc/nginx/sites-available/abc.abc,内容如下(根据你的实际端口修改,比如Web应用跑8080,API跑5000):server { listen 80; server_name abc.abc; return 301 https://$host$request_uri; # 把所有HTTP请求跳转到HTTPS } server { listen 443 ssl; server_name abc.abc; # 填你之前获取的SSL证书路径 ssl_certificate /etc/letsencrypt/live/abc.abc/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/abc.abc/privkey.pem; # 转发Web应用的请求(根路径) location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 转发API的请求(用/api前缀区分,比如你的API接口是/api/get-data) location /api { proxy_pass http://localhost:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }启用配置并重启Nginx:
sudo ln -s /etc/nginx/sites-available/abc.abc /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置是否正确 sudo systemctl restart nginx
之后Web应用调用https://abc.abc/api就能正常访问API了,全程都是HTTPS,不会触发混合内容限制。
方案三:临时放宽浏览器限制(仅测试用,生产绝对禁止)
如果只是本地测试不想折腾配置,可以临时让浏览器允许混合内容:
- Chrome:地址栏输入
chrome://flags/#allow-insecure-localhost,启用这个选项后重启浏览器 - Firefox:地址栏输入
about:config,搜索security.mixed_content.block_active_content,把值改成false
这个方法只适合自己测试用,绝对不能用于生产环境,会带来安全风险。
内容的提问来源于stack exchange,提问作者Zafar

