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以及代碼層次的修改(前后端),我這邊是時間問題。。