利用HSTS安全協(xié)議柔性解決全站HTTPS的兼容性問題

導(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é)議柔性解決全站HTTPS的兼容性問題

一、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安全協(xié)議柔性解決全站HTTPS的兼容性問題

而不支持 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è)月都是有可能的:利用HSTS安全協(xié)議柔性解決全站HTTPS的兼容性問題

好了,羅里吧嗦分享了一大堆,自行參考吧!

20170205 最新補(bǔ)充:經(jīng)過漫長的等待,偶然查詢發(fā)現(xiàn)已經(jīng)是 preload 狀態(tài)了,可真不容易:利用HSTS安全協(xié)議柔性解決全站HTTPS的兼容性問題

本文:https://zhangge.net/5115.html

轉(zhuǎn)載請注明出處 AE博客|墨淵 ? 利用HSTS安全協(xié)議柔性解決全站HTTPS的兼容性問題

發(fā)表評論

路人甲

網(wǎng)友評論(0)