導(dǎo)讀:目前,很多站都開始實(shí)現(xiàn) HTTPS 了,而且其中的大部分強(qiáng)迫癥站長還會開啟強(qiáng)制 HTTPS 機(jī)制,對于網(wǎng)站的 HTTP 請求全部 301 跳轉(zhuǎn)到 HTTPS,從而實(shí)現(xiàn)全站 HTTPS。這明顯是一個(gè)粗暴的做法,下面張戈博客就分享一下目前正在使用的柔性做法,告別粗暴。
一、HSTS 協(xié)議
這里我們要借助一個(gè)新的安全協(xié)議:HSTS
HSTS(HTTP Strict Transport Security)國際互聯(lián)網(wǎng)工程組織 IETE 正在推行一種新的 Web 安全協(xié)議,作用是強(qiáng)制客戶端(如瀏覽器)使用 HTTPS 與服務(wù)器創(chuàng)建連接。
主要目的是為了解決 HTTPS 網(wǎng)站首次請求時(shí)使用的是未加密的 HTTP 協(xié)議,也就說用戶一般訪問我們的網(wǎng)站都是直接在瀏覽器輸入域名,比如 zhangge.net,然后我們的服務(wù)器檢測到是 HTTP 請求,就 301 跳轉(zhuǎn)到 HTTPS 頁面。那么前半程采用的就是未加密的 HTTP 請求,同樣存在被劫持的可能,那么 HTTPS 說好的安全性也就大打折扣了!
在我看來,HSTS 還有另外一層好處:增強(qiáng)網(wǎng)站的兼容性。
以往分享的全站 HTTPS 都是采用 301 強(qiáng)制性跳轉(zhuǎn),而且還會區(qū)分下低版本 IE、不支持 HTTPS 的搜索引擎來忽略 301 跳轉(zhuǎn),很明顯這樣做無法照顧到所有情況。那么如果是用 HSTS 呢?
采用 HSTS 后,支持這個(gè)協(xié)議的瀏覽器會自動跳轉(zhuǎn)到 HTTPS 頁面,返回碼為 307:
而不支持 HSTS 的瀏覽器訪問我們的網(wǎng)站,則不會產(chǎn)生跳轉(zhuǎn),從而提高了兼容性。這個(gè)機(jī)制對于不支持 HTTPS 的搜索引擎來說是非常友好的做法了!
二、開啟 HSTS
開啟 HSTS 很簡單,只要在我們網(wǎng)站的響應(yīng)頭里面新增 HSTS 即可,下面簡單說下
①、Nginx 服務(wù)器
只需要在站點(diǎn) server 模塊內(nèi)插入如下配置并重啟:
server { listen 443 ssl http2; server_name zhangge.net; # 直接在server插入測試居然不生效,最后發(fā)現(xiàn)要在location ~ *php 內(nèi)插入: location ~ [^/]\.php(/|$) { add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; # 以下略...
②、Apache 服務(wù)器
Apache 如下配置并重啟:
# 先在Apache加載mod_header庫,一般位于httpd.conf文件,自行搜索mod_headers并取消注釋 LoadModule headers_module modules/mod_headers.so #然后在站點(diǎn)VirtualHost里面插入HSTS響應(yīng)頭信息,比如:Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
③、LigHttpd
將下述配置增加到你的 Lighttpd 配置文件(一般是 /etc/lighttpd/lighttpd.conf)并重啟:
server.modules += ( "mod_setenv" ) $HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload") }
④、通用方法
如果你用的虛擬主機(jī),或者不會折騰 WEB 軟件,那么可以采用更簡單的通用方法。原理很簡單,通過代碼來新增響應(yīng)頭即可,這里只分享一下 php 的做法,其他語言自行參考:
將如下代碼插入到網(wǎng)站根目錄的 index.php 即可:
header("Strict-Transport-Security: max-age=63072000; includeSubdomains; preload");
三、相對鏈接
當(dāng)然,為了兼容不支持 HTTPS 的客戶端,我們還需要將網(wǎng)站的所有超鏈接都改成相對模式:
比如,正常的頁面鏈接如下所示:
<a target="_blank">描文本</a>
改成相對模式:
<a target="_blank">描文本</a>
好處就是,不管是 HTTP 還是 HTTPS 請求,頁面中的地址都是和請求協(xié)議保持一致,避免出現(xiàn)頁面是 HTTP,而頁面中的鏈接卻是 HTTPS 的情況,那么前面的做法也就沒了意義。
如何修改為相對模式,估計(jì)有同學(xué)又玩不轉(zhuǎn)了。萬變不離其宗,和以前純代碼啟用七牛 CDN 一樣!
直接粗暴替換前臺輸出的代碼即可:
//將所有超鏈接改為相對模式 if(!is_admin()){ ob_start("rewrite_urls"); } function rewrite_urls($buffer){ $buffer= preg_replace('/("|\')http(s|):\/\/([^"\']*?)'.$_SERVER["HTTP_HOST"].'/i','$1//$3'.$_SERVER["HTTP_HOST"],$buffer); return $buffer; }
將以上代碼新增到 WordPress 主題的 functions.php 中即可。以上代碼只會替換和網(wǎng)站主域名有關(guān)系的超鏈接,八竿子打不著的外部超鏈接就不管了,有需求自行參考解決。
四、提交 HSTS
上文已介紹了 HSTS,主要是為了解決 HTTP 請求 301 跳轉(zhuǎn)到 HTTPS 這個(gè)過程被劫持問題,而實(shí)際上就算加上 HSTS 響應(yīng)頭,用戶請求的前半程依然是 HTTP,并沒有什么 L 用。
提出這個(gè)協(xié)議的磚家們就想出了一個(gè)解決辦法:將支持 HSTS 的網(wǎng)站全部加入一個(gè) Preload 的清單,支持 HSTS 協(xié)議的瀏覽器請求網(wǎng)站前會查詢當(dāng)前網(wǎng)站是否在清單中,如果是那么直接轉(zhuǎn)換為 HTTPS 請求!從而解決前半程為 HTTP 的問題(不專業(yè),但說人話。。。)。
那么,如果我們的網(wǎng)站啟用了 HSTS,還得將網(wǎng)站提交到這個(gè) Preload 清單才行了
提交地址:https://hstspreload.appspot.com/ (需要扶墻訪問)
提交直到批準(zhǔn),我們的網(wǎng)站必須強(qiáng)制 301 跳轉(zhuǎn)到 HTTPS,否則無法通過,完成審核后再取消 301 即可。
當(dāng)然,提交后會顯示正在提交到 preload list,快的話兩三天,慢的話一兩個(gè)月都是有可能的:
好了,羅里吧嗦分享了一大堆,自行參考吧!
20170205 最新補(bǔ)充:經(jīng)過漫長的等待,偶然查詢發(fā)現(xiàn)已經(jīng)是 preload 狀態(tài)了,可真不容易:
本文:https://zhangge.net/5115.html
轉(zhuǎn)載請注明出處 AE博客|墨淵 ? 利用HSTS安全協(xié)議柔性解決全站HTTPS的兼容性問題
發(fā)表評論