Google Chrome升级到81.x之后会自发的将原来的http请求转化成https(你返回给前端的uri可能是http开头的但是实际调用资源的时候会自动转化成https),但是其他浏览器暂时不会。那么那些原来通过http访问资源的操作就要考虑两个问题:
1.如何让资源能通过https的方式获取
2.如何让同样的uri可以通过不同的协议获取(或者简单的说如何让http 和https指向一个端口)。
笔者就碰到了这样的问题,我们公司原来的视频资源是通过nginx+fastdfs的方式实现的,原nginx配置如下:
server {
listen 8080;
server_name www.domain.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location /group0/ {
limit_conn perip 2;
limit_conn perserver 4;
limit_rate 512k;
root /home/xx/cloud_storage/storage/storage_data/data;
if ($args ~ customname=([^&]*.[^&]*)) {
set $fname $1;
}
if ($args ~ action=download) {
add_header Content-Disposition "attachment; filename=$fname";
}
ngx_fastdfs_module;
}
........
这里监控的是8080端口,接受http的请求。后端返回给前端的uri是http://www.domain.com:8080/group0/x/x/x/x/x
经过Google Chrome升级到81.x之后转化就变成了https://www.domain.com:8080/group0/x/x/x/x/x,这个时候去看/logs/access.log可以看到会有一个乱码的请求过来,当然了因为nginx没配置ssl。
现在解决第一个问题为nginx配置ssl:
第一步,开启ssl_module,进入nginx的源文件,重新执行configure 在你原来的./configure 命令后边加上一个参数--with-http_ssl_module,然后make,把新生成的/sbin/nginx文件替换老的。./nginx -V检查是否开启ssl_module
第二步,创建密钥,可以使用openssl生成的或者购买ca认证,我用的生成的文件分别是
/home/ubuntu/xx/xx/cloud_storage/nginx/conf/server.pem和/home/ubuntu/xx/xx/cloud_storage/nginx/conf/privkey.pem
第三步,把上边的配置文件修改一下。修改为:
server {
listen 8080;
ssl on;
ssl_certificate /home/ubuntu/xx/xx/cloud_storage/nginx/conf/server.pem;
ssl_certificate_key /home/ubuntu/xx/xx/cloud_storage/nginx/conf/privkey.pem;
server_name www.domain.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location /group0/ {
........
添加了
ssl on;
ssl_certificate /home/ubuntu/xx/xx/cloud_storage/nginx/conf/server.pem;
ssl_certificate_key /home/ubuntu/xx/xx/cloud_storage/nginx/conf/privkey.pem;
至此https请求能拉取到资源了,但是问题来了,当客户用非chrome浏览或者chrome低版本浏览的时候使用的还是http请求,当然了你可以说让前端改一下强制都用https不就行了吗?这是一种方法但是我用了另外一种
我做完上边的修改之后注意到用http访问资源的时候出错了:400 Bad Request: The plain HTTP request was sent to HTTPS port
说的很明确http的请求发送到了https的port上 也就是8080.那么有一个取巧的方法就是利用nginx的error_page配置指定错误代码为xx的时候强制跳转成https,这样就能获取到了
添加 error_page 400 https://$host:8080$uri;
server {
listen 8080;
ssl on;
ssl_certificate /home/ubuntu/xx/xx/cloud_storage/nginx/conf/server.pem;
ssl_certificate_key /home/ubuntu/xx/xx/cloud_storage/nginx/conf/privkey.pem;
server_name www.domain.com;
error_page 400 https://$host:8080$uri;
#charset koi8-r;
#access_log logs/host.access.log main;
location /group0/ {
........
400合适吗?400明显不合适。因为400涵盖的面太广了,主要是同事提出了不同的意见认为如果我这么写如果url里面已经配置了errorlink那么会不会冲突,
仔细思考确实,又查了点资料发现497 - normal request was sent to HTTPS,这个才是http发送到https的时候的真正的error code,于是配了
error_page 497 https://$host:8080$uri;
至此问题解决,等待测试反馈。但是这么写总觉得有点隐患,所以推荐的做法还是总体上把http升级到https包括nginx以及代码层次的修改(前后端),我这边是时间问题。。