因爲HTTP自己不具有加密的功能,因此也沒法作到對通訊總體(使用HTTP協議通訊的請求和響應的內容)進行加密。即,HTTP報文使用明文(指未通過加密的報文)方式發送。web
按TCP/IP協議族的工做機制,通訊內容在全部的通訊線路上都有可能遭到窺視。api
即便已通過加密處理的通訊,也會被窺視到通訊內容,這點和未加密的通訊是相同的。只是說若是通訊通過加密,就有可能讓人沒法破解報文信息的含義,但加密處理後的報文信息自己仍是會被看到的。瀏覽器
最爲普及的就是加密技術。安全
用SSL創建安全通訊線路以後,就能夠在這條線路上進行HTTP通訊了。與SSL組合使用的HTTP被稱爲HTTPS(HTTP Secure,超文本傳輸安全協議)或HTTPover SSL。bash
誠然,爲了作到有效的內容加密,前提是要求客戶端和服務器同時具有加密和解密機制。主要應用在Web服務中。有一點必須引發注意,因爲該方式不一樣於SSL或TLS將整個通訊線路加密處理,因此內容仍有被篡改的風險。服務器
HTTP協議中的請求和響應不會對通訊方進行確認。websocket
在HTTP協議通訊時,因爲不存在確認通訊方的處理步驟,任何人均可以發起請求。另外,服務器只要接收到請求,無論對方是誰都會返回一個響應(但也僅限於發送端的IP地址和端口號沒有被Web服務器設定限制訪問的前提下)。不確認通訊方,會存在如下各類隱患。網絡
雖然使用HTTP協議沒法肯定通訊方,但若是使用SSL則能夠。SSL不只提供加密處理,並且還使用了一種被稱爲證書的手段,可用於肯定方。多線程
證書由值得信任的第三方機構頒發,用以證實服務器和客戶端是實際存在的。另外,僞造證書從技術角度來講是異常困難的一件事。因此只要可以確認通訊方(服務器或客戶端)持有的證書,便可判斷通訊方的真實意圖。併發
因爲HTTP協議沒法證實通訊的報文完整性,所以,在請求或響應送出以後直到對方接收以前的這段時間內,即便請求或響應的內容遭到篡改,也沒有辦法獲悉。
好比,從某個Web網站上下載內容,是沒法肯定客戶端下載的文件和服務器上存放的文件是否先後一致的。文件內容在傳輸途中可能已經被篡改成其餘的內容。即便內容真的已改變,做爲接收方的客戶端也是覺察不到的。像這樣,請求或響應在傳輸途中,遭攻擊者攔截並篡改內容的攻擊稱爲中間人攻擊(Man-in-the-Middleattack,MITM)。
雖然有使用HTTP協議(頭部字段Content-MD5)肯定報文完整性的方法,但事實上並不便捷、可靠。其中經常使用的是MD5和SHA-1等散列值校驗的方法,以及用來確認文件的數字簽名方法。
若是在HTTP協議通訊過程當中使用未經加密的明文,好比在Web頁面中輸入信用卡號,若是這條通訊線路遭到竊聽,那麼信用卡號就暴露了。
另外,對於HTTP來講,服務器也好,客戶端也好,都是沒有辦法確認通訊方的。由於頗有可能並非和本來預想的通訊方在實際通訊。而且還須要考慮到接收到的報文在通訊途中已經遭到篡改這一可能性。
爲了統一解決上述這些問題,須要在HTTP上再加入加密處理和認證等機制。咱們把添加了加密及認證機制的HTTP稱爲HTTPS(HTTP Secure)。
HTTPS並不是是應用層的一種新協議。只是HTTP通訊接口部分用SSL(Secure Socket Layer)和TLS(TransportLayer Security)協議代替而已。
一般,HTTP直接和TCP通訊。當使用SSL時,則演變成先和SSL通訊,再由SSL和TCP通訊了。簡言之,所謂HTTPS,其實就是身披SSL協議這層外殼的HTTP。
SSL是獨立於HTTP的協議,因此不光是HTTP協議,其餘運行在應用層的SMTP和Telnet等協議都可配合SSL協議使用。能夠說SSL是當今世界上應用最爲普遍的網絡安全技術。
計算機自己沒法判斷坐在顯示器前的使用者的身份。進一步說,也沒法確認網絡的那頭究竟有誰。可見,爲了弄清到底是誰在訪問服務器,就得讓對方的客戶端自報家門。
爲確認用戶是否真的具備訪問系統的權限,就須要覈對「登陸者本人才知道的信息」、「登陸者本人才會有的信息」
覈對的信息一般是指如下這些。
BASIC認證(基本認證)是從HTTP/1.0就定義的認證方式。即使是如今仍有一部分的網站會使用這種認證方式。是Web服務器與通訊客戶端之間進行的認證方式。
BASIC認證雖然採用Base64編碼方式,但這不是加密處理。不須要任何附加信息便可對其解碼。換言之,因爲明文解碼後就是用戶ID和密碼,在HTTP等非加密通訊的線路上進行BASIC認證的過程當中,若是被人竊聽,被盜的可能性極高。
BASIC認證使用上不夠便捷靈活,且達不到多數Web網站指望的安全性等級,所以它並不經常使用。
爲彌補BASIC認證存在的弱點,從HTTP/1.1起就有了DIGEST認證。DIGEST認證一樣使用質詢/響應的方式,但不會像BASIC認證那樣直接發送明文密碼。
所謂質詢響應方式是指,一開始客戶端會先發送認證要求給服務端,服務端發送質詢碼給客戶端,接着客戶端使用接收到的質詢碼計算生成響應碼。最後將響應碼返回給對方進行認證的方式。
DIGEST認證提供了高於BASIC認證的安全等級,可是和HTTPS的客戶端認證相比仍舊很弱。DIGEST認證提供防止密碼被竊聽的保護機制,但並不存在防止用戶假裝的保護機制。
從使用用戶ID和密碼的認證方式方面來說,只要兩者的內容正確,便可認證是本人的行爲。但若是用戶ID和密碼被盜,就頗有可能被第三者冒充。利用SSL客戶端認證則能夠避免該狀況的發生。
SSL客戶端認證是藉由HTTPS的客戶端證書完成認證的方式。憑藉客戶端證書(在HTTPS一章已講解)認證,服務器可確認訪問是否來自已登陸的客戶端。
使用SSL客戶端認證須要用到客戶端證書。而客戶端證書須要向認證機構購買。
基於表單的認證方法並非在HTTP協議中定義的。客戶端會向服務器上的Web應用程序發送登陸信息(Credential),按登陸信息的驗證結果認證。
多數狀況下,輸入已事先登陸的用戶ID(一般是任意字符串或郵件地址)和密碼等登陸信息後,發送給Web應用程序,基於認證結果來決定認證是否成功。
因爲使用上的便利性及安全性問題,HTTP協議標準提供的BASIC認證和DIGEST認證幾乎不怎麼使用。另外,SSL客戶端認證雖然具備高度的安全等級,但由於導入及維持費用等問題,還還沒有普及。
基於表單認證自己是經過服務器端的Web應用,將客戶端發送過來的用戶ID和密碼與以前登陸過的信息作匹配來進行認證的。
但鑑於HTTP是無狀態協議,以前已認證成功的用戶狀態沒法經過協議層面保存下來。即,沒法實現狀態管理,所以即便當該用戶下一次繼續訪問,也沒法區分他與其餘的用戶。因而咱們會使用Cookie來管理Session,以彌補HTTP協議中不存在的狀態管理功能。
在創建HTTP標準規範時,制訂者主要想把HTTP看成傳輸HTML文檔的協議。隨着時代的發展,Web的用途更具多樣性,好比演化成在線購物網站、SNS(SocialNetworking Service,社交網絡服務)、企業或組織內部的各類管理工具,等等。
而這些網站所追求的功能可經過Web應用和腳本程序實現。即便這些功能已經知足需求,在性能上卻未必最優,這是由於HTTP協議上的限制以及自身性能有限。
HTTP功能上的不足可經過建立一套全新的協議來彌補。但是目前基於HTTP的Web瀏覽器的使用環境已遍及全球,所以沒法徹底拋棄HTTP。有一些新協議的規則是基於HTTP的,並在此基礎上添加了新的功能。
Google在2010年發佈了SPDY,其開發目標旨在解決HTTP的性能瓶頸,縮短Web頁面的加載時間(50%)。
在Facebook和Twitter等SNS網站上,短的時間內就會發生大量的內容更新。
爲了儘量實時地顯示這些更新的內容,服務器上一有內容更新,就須要直接把那些內容反饋到客戶端的界面上。雖然看起來挺簡單的,但HTTP卻沒法妥善地處理好這項任務。
使用HTTP協議探知服務器上是否有內容更新,就必須頻繁地從客戶端到服務器端進行確認。若是服務器上沒有內容更新,那麼就會產生徒勞的通訊。
SPDY以會話層的形式加入,控制對數據的流動,但仍是採用HTTP創建通訊鏈接。所以,可照常使用HTTP的GET和POST等方法、Cookie以及HTTP報文等。
多路複用流。
經過單一的TCP鏈接,能夠無限制處理多個HTTP請求。全部請求的處理都在一條TCP鏈接上完成,所以TCP的處理效率獲得提升。
請求優先級
SPDY不只能夠無限制地併發處理請求,還能夠給請求逐個分配優先級順序。這樣主要是爲了在發送多個請求時,解決因帶寬低而致使響應變慢的問題。
壓縮HTTP首部
這樣一來,通訊產生的數據包數量和發送的字節數就更少了。
推送功能
支持服務器主動向客戶端推送數據的功能。這樣,服務器可直接發送數據,而沒必要等待客戶端的請求。
AJAX不是JavaScript的規範,它只是一個哥們「發明」的縮寫:Asynchronous JavaScript and XML,意思就是用JavaScript執行異步網絡請求。
Ajax(Asynchronous JavaScript and XML,異步JavaScript與XML技術)是一種有效利用JavaScript和DOM(Document Object Model,文檔對象模型)的操做,以達到局部Web頁面替換加載的異步通訊手段。和之前的同步通訊相比,因爲它只更新一部分頁面,響應中傳輸的數據量會所以而減小,這一優勢顯而易見。
Ajax的核心技術是名爲XMLHttpRequest的API,經過JavaScript腳本語言的調用就能和服務器進行HTTP通訊。藉由這種手段,就能從已加載完畢的Web頁面上發起請求,只更新局部頁面。
引用廖雪峯老師的例子(利用XMLHttpRequest來作請求)
'use strict';
----
function success(text) {
var textarea = document.getElementById('test-response-text');
textarea.value = text;
}
function fail(code) {
var textarea = document.getElementById('test-response-text');
textarea.value = 'Error code: ' + code;
}
var request = new XMLHttpRequest(); // 新建XMLHttpRequest對象
request.onreadystatechange = function () { // 狀態發生變化時,函數被回調
if (request.readyState === 4) { // 成功完成
// 判斷響應結果:
if (request.status === 200) {
// 成功,經過responseText拿到響應的文本:
return success(request.responseText);
} else {
// 失敗,根據響應碼判斷失敗緣由:
return fail(request.status);
}
} else {
// HTTP請求還在繼續...
}
}
// 發送請求:
request.open('GET', '/api/categories');
request.send();
alert('請求已發送,請等待響應...');
複製代碼
一旦服務器端有內容更新了,Comet不會讓請求等待,而是直接給客戶端返回響應。這是一種經過延遲應答,模擬實現服務器端向客戶端推送(Server Push)的功能。
一般,服務器端接收到請求,在處理完畢後就會當即返回響應,但爲了實現推送功能,Comet會先將響應置於掛起狀態,當服務器端有內容更新時,再返回該響應。所以,服務器端一旦有更新,就能夠當即反饋給客戶端。
內容上雖然能夠作到實時更新,但爲了保留響應,一次鏈接的持續時間也變長了。期間,爲了維持鏈接會消耗更多的資源。
不少網站爲了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費不少的帶寬等資源。
而比較新的技術去作輪詢的效果是Comet。這種技術雖然能夠雙向通訊,但依然須要反覆發出請求。並且在Comet中,廣泛採用的長連接,也會消耗服務器資源。
Comet本質上也是輪詢,可是在沒有消息的狀況下,服務器先拖一段時間,等到有消息了再回復。這個機制暫時地解決了實時性問題,可是它帶來了新的問題:以多線程模式運行的服務器會讓大部分線程大部分時間都處於掛起狀態,極大地浪費服務器資源。另外,一個HTTP鏈接在長時間沒有數據傳輸的狀況下,鏈路上的任何一個網關均可能關閉這個鏈接,而網關是咱們不可控的,這就要求Comet鏈接必須按期發一些ping數據表示鏈接「正常工做」。
在這種狀況下,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬,而且可以更實時地進行通信。
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13
複製代碼
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string
複製代碼
該響應代碼101表示本次鏈接的HTTP協議即將被更改,更改後的協議就是Upgrade: websocket指定的WebSocket協議。
版本號和子協議規定了雙方能理解的數據格式,以及是否支持壓縮等等。若是僅使用WebSocket的API,就不須要關心這些。
如今,一個WebSocket鏈接就創建成功,瀏覽器和服務器就能夠隨時主動發送消息給對方。消息有兩種,一種是文本,一種是二進制數據。一般,咱們能夠發送JSON格式的文本,這樣,在瀏覽器處理起來就十分容易。
WebSocket並非全新的協議,而是利用了HTTP協議來創建鏈接。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。
在 WebSocket API 中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。
因爲是創建在HTTP基礎上的協議,所以鏈接的發起方還是客戶端,而一旦確立WebSocket通訊鏈接,不論服務器仍是客戶端,任意一方均可直接向對方發送報文。
爲何WebSocket鏈接能夠實現全雙工通訊而HTTP鏈接不行呢?實際上HTTP協議是創建在TCP協議之上的,TCP協議自己就實現了全雙工通訊,可是HTTP協議的請求-應答機制限制了全雙工通訊。WebSocket鏈接創建之後,其實只是簡單規定了一下:接下來,我們通訊就不使用HTTP協議了,直接互相發數據吧。
安全的WebSocket鏈接機制和HTTPS相似。首先,瀏覽器用wss://xxx建立WebSocket鏈接時,會先經過HTTPS建立安全的鏈接,而後,該HTTPS鏈接升級爲WebSocket鏈接,底層通訊走的仍然是安全的SSL/TLS協議。
推送功能
支持由服務器向客戶端推送數據的推送功能。這樣,服務器可直接發送數據,而沒必要等待客戶端的請求。
減小通訊量
只要創建起WebSocket鏈接,就但願一直保持鏈接狀態。和HTTP相比,不但每次鏈接時的總開銷減小,並且因爲WebSocket的首部信息很小,通訊量也相應減小了。
成功握手確立WebSocket鏈接以後,通訊時再也不使用HTTP的數據幀,而採用WebSocket獨立的數據幀。
很顯然,要支持WebSocket通訊,瀏覽器得支持這個協議,這樣才能發出ws://xxx的請求。目前,支持WebSocket的主流瀏覽器以下:
HTTP/2.0在2014年11月實現標準化。
HTTP/2.0的目標是改善用戶在使用Web時的速度體驗。
有如下幾個目標: