前面我們介紹了Kerberos/NTLM驗證,也實地觀察過HTTP 401、401、200的歷程。登入網站只輸入一次密碼,想當然爾同一個身分驗證可用來存取後續的css、js、jpg、gif… 若是每次讀檔都401、401、200重新走一次,未免太沒效率。

隨便開個Windows驗證的網頁,Fiddler側錄結果卻又讓人迷惑。如下圖範例,網頁default.aspx引用一堆js、css,就觸發了成串HTTP 401,這回是401後接200,兩個Request/Response往返就完成。但也有例外,像是第5個/AfaClient/css/jquery.tab.css就沒出現401,一次200搞定,這到底是怎麼一回事?

用個實驗來說明:

<html>
<head>
    <title>HTTP 401 Test</title>
</head>
<body>
    <button>Test</button>
    <script src="http://code.jquery.com/jquery-2.2.3.min.js">
    </script>
    <script>
    $("button").click(function() {
        $.get("/magicwand.gif?t=" + Math.random());
    });
    </script>
</body>
</html>

test1.html是個簡單網頁,按鈕後用jQuery.get()取回magicwand.gif圖檔(URL加上亂數避免快取)。test1.html、magicwand.gif二者都需Windows驗證。以下是載入網頁後按鈕三次的Fiddler側錄結果:

除了/Test1.html載入時歷經401、401、200,之後讀取magicwand.gif都是一次200到位不囉嗦,關鍵在這裡:

Test1.html回傳Response Header中有個Persistent-Auth: true,宣告這條連線可以沿用身分認證,而Request Header約定連線採Keep-Alive模式,讀完資料後保留TCP連線供後續使用(節省重建連線成本,提高效率)。於是再送出的GET magicwand.gif就不需要驗證,快速通關。如下圖所示,Request沒有包含Authorization Header,就能直接得到HTTP 200。

由以上可知,連線再驗證後就不需要401、200的過程,可以直接200取回內容。

再看另一個實驗:

<html>
<head>
    <title>HTTP 401 Test</title>
</head>
<body>
    <button>Test</button>
    <script src="http://code.jquery.com/jquery-2.2.3.min.js">
    </script>
    <script>
    $("button").click(function() {
        for (var i = 0; i < 32; i++) {
            $.get("/magicwand.gif?n=" + i + 
                  "&t=" + Math.random());
        }
    });
    </script>
</body>
</html>

這回我們狠一點,一口氣同步送出32個$.get(),結果就不太一樣了:

初期出現一大堆401,但後期就清一色都是200。仔細數數,扣除Test2.html的兩個401,還出現11次401。為什麼?記得剛才有提到「Response出現Persistent-Auth: true 代表這條Keep-Alive連線可沿用身分認證」,而當我們同時發出多個HTTP請求時,瀏覽器不會呆呆的只用一條連線抓完這個再抓下一個,而會建立多條連線同時下載。這個觀念之前在IE MaxConnectionsPerServer參數效果實測一文曾研究過,當時測試的對象是IE8,預設最大同時連線數是6條,我沒找到記載 IE11@Windows 10最大同時連線數預設值的文件,但由觀測結果來看是12條。回頭數數第一張圖中的401數目,扣除default.apsx有兩個401,總數也是12個。所以,每次新建連線後要走一次401、200過程,之後靠Persistent-Auth沿用驗證,就不要需要401。

另外補充,IIS是否允許Perisistent-Auth是可以設定的,詳情可參考MSDN文件,而NTLM與Kerberos的設定是分開的,NTLM預設就有,Kerberos需要額外開啟

結論:使用Windows驗證時,Perisitent-Auth功能允許一條連線只需驗證一次,後續不必每次先401再200,以提升效能。當瀏覽器同時發出多個HTTP Request時,背後會新建多條HTTP連線,每條新建連線必須先走一次401再200的驗證步驟,後續則可免除401的過程。IIS預設NTLM已開啟Persistent-Auth,Kerberos則需額外設定。


Comments

Be the first to post a comment

Post a comment