http與Https協(xié)議詳解介紹
http協(xié)議大家可能都耳熟能詳了,但是它有一系列的缺點,比如:
1.通信時使用明文,這樣有可能通信內(nèi)容會被竊聽;
2.不會驗證通信方的身份,包括服務(wù)器和客戶端,特別是服務(wù)器,有可能你發(fā)送請求的對方是個釣魚網(wǎng)站;
3.無法驗證報文的完整性(準(zhǔn)確度),有可能所有的報文會經(jīng)過黑客的服務(wù)器,黑客將內(nèi)容篡改后進行轉(zhuǎn)發(fā),前后端都不會知曉,神不知鬼不覺;
雖然http協(xié)議已經(jīng)非常強大了,但在安全這一塊確實是還有欠妥之處,于是一種安全的http協(xié)議-https運用而生。
Https概述
https并不是一種新的協(xié)議,只是在http層下面添加了一層SSL層和TLS層(后面統(tǒng)稱為SSL層),SSL層主要是做加密處理,http層直接與SSL層通信,如下圖所示:

一、加密技術(shù)
為了更好的了解https,從而保證了數(shù)據(jù)的安全性。下面介紹https用到的2種加密方式:
1.共享密鑰加密(對稱密鑰加密)
加密和解密用同一個密鑰的方式,這種方式需要客戶端和服務(wù)器都知道這個密鑰,而單獨的發(fā)送這個密鑰有可能會被竊聽的風(fēng)險,所以如何安全的發(fā)送這個密鑰又是一個新的難題。
所以尷尬境地是:發(fā)送密鑰吧,有可能被黑客竊取;不發(fā)送密鑰吧,對方就不能解密。
2.公開密鑰加密(非對稱密鑰加密)
這里使用了2把密鑰,一把叫私有密鑰(私鑰),一把叫公開密鑰(公鑰),這2個密鑰是配對的一套密鑰,公鑰可以讓任何人都知道,而私鑰只有自己知道。
另外,對于一對公鑰私鑰而言:公鑰加密的內(nèi)容,只有私鑰才能解開;而私鑰加密的內(nèi)容,所有公鑰都可以解開。
這種方式可以很好的解決上面對稱密鑰加密方式的尷尬境地:對于一段內(nèi)容,發(fā)送方可以使用公鑰進行加密發(fā)送給對方,接收方收到內(nèi)容后用自己的私鑰進行解密,因為這樣不用發(fā)送解密的私鑰,從而不會落入黑客之手。
有的人會有這樣的擔(dān)心:難道黑客就不能截獲加密的內(nèi)容后破解加密的內(nèi)容嗎?但是我告訴你,破解的難度相當(dāng)大,就目前的技術(shù)來看不太現(xiàn)實。
二、混合加密技術(shù)-HTTPS
https采用上面2種加密方式的混合加密機制(公開密鑰加密+共享密鑰加密),共享密鑰加密方式的密鑰用公開密鑰加密方式加密后發(fā)送給對方,然后建立通信后的內(nèi)容采用共享密鑰加密方式。
為什么采用這種混合方式呢?因為公開加密方式與共享加密方式相比,它的處理速度要慢,所以采用公開加密方式加密一次共享加密方式的密鑰后,后面的內(nèi)容則多次采用共享加密方式,這樣可以大大增加效率。

三、安全隱患
但是單純的采用這種混合加密方式,還是會出現(xiàn)安全問題。為什么呢?設(shè)想一下,如果第一步向服務(wù)器請求公鑰的時候,服務(wù)器會返回真實的公鑰,這時候如果有黑客在中間做一些調(diào)包及轉(zhuǎn)發(fā)工作,客戶端無法知曉對方的服務(wù)器是否是真實的服務(wù)器。為了解決這一安全問題,于是又添加了證書這一機制。
證書
數(shù)字證書(證書)由數(shù)字證書認證機構(gòu)(簡稱CA)頒發(fā)。CA何許人也?它是客戶端和服務(wù)器雙方都可信賴的權(quán)威的第三方機構(gòu)。它的任務(wù)就是頒發(fā)證書,一般是給服務(wù)器頒發(fā)證書,頒發(fā)證書后就意味著這個服務(wù)器網(wǎng)站是值得信賴的;也可給客戶端頒發(fā)證書,但一般這種情況比較少見,只用在一些特殊的業(yè)務(wù),比如:網(wǎng)上銀行等。
四、獲取證書
如何獲取證書呢?當(dāng)然是向CA申請及購買,交完錢后,它會給你服務(wù)器頒發(fā)一個證書。
也可以免費申請證書,比如:FreeSSL
有人可能會關(guān)心購買證書的價格,這里隨便在網(wǎng)上截了個圖,可以大概了解下

五、證書的主要內(nèi)容
證書中主要包含有:頒發(fā)對象的信息,頒發(fā)者,過期時間,數(shù)字簽名等,完整信息如下圖:

拿百度網(wǎng)站為例,若是https網(wǎng)站,網(wǎng)址前面會有一把鎖,可以查看證書,也可導(dǎo)出證書。


一、數(shù)字簽名的重要性
從上圖可以看到,證書中都會有數(shù)字簽名,那么什么是數(shù)字簽名呢?
數(shù)字簽名其實就是特殊的加密校驗碼,客戶端在收到證書后會用瀏覽器內(nèi)置的CA相應(yīng)公鑰根據(jù)簽名算法對目標(biāo)網(wǎng)站進行本地簽名,如果本地簽名與證書的簽名不一樣,則判定對方服務(wù)器是冒牌貨,停止傳輸。
上面提到為什么會用到瀏覽器內(nèi)置的CA公鑰呢?
數(shù)字證書認證機構(gòu)的公開密鑰必須安全的轉(zhuǎn)交給客戶端,那么如何轉(zhuǎn)交又是一件很困難的事(唉!困難重重啊!),于是解決辦法是:大多數(shù)瀏覽器開發(fā)商在發(fā)布版本時,會事先在瀏覽器內(nèi)部植入常用認證機構(gòu)的公開密鑰。
HTTPS加密傳輸流程
通過上面一些基本知識講解,可以更好的理解https到底是怎么工作,怎么保證網(wǎng)絡(luò)安全的,流程如下:
1、瀏覽器請求目標(biāo)網(wǎng)站,服務(wù)器把證書發(fā)送給客戶端
2、客戶端會對證書進行本地簽名校驗(參考上面的數(shù)字簽名的重要性)
3、若校驗成功,則客戶端瀏覽器會隨機生成一個共享加密方式(對稱加密)的密鑰,然后會從證書中提取公鑰對剛剛生成的密鑰進行加密,得到密文并發(fā)送給服務(wù)器
4、服務(wù)器收到密文后用自己的私鑰進行解密,得到共享加密方式的密鑰
5、接下來的一系列的報文傳輸就采用共享加密方式,因為此時雙方(客戶端、服務(wù)器)都擁有了共享加密方式的密鑰,接下來就可以安全的愉快的玩耍了

Python代碼中關(guān)于SSL驗證的問題
在我們寫代碼時請求https網(wǎng)站時經(jīng)常會出現(xiàn)類似“certificate verify failed”這樣的錯誤。
這樣的錯誤意思是SSL驗證出錯的問題,說白了,其實就是上面提到的數(shù)字簽名的校驗的錯誤。以Requests庫為例,內(nèi)部引入了pyOpenSSL庫
出現(xiàn)SSL錯誤的代碼:
import requests headers = { 'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/59.0' } r = requests.get('https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx', verify= True) print(r.status_code)
結(jié)果如下所示:

參數(shù)verify默認為True。其實就是對證書驗證失敗,驗證的目的就是確認請求的目標(biāo)服務(wù)器是不是真實的服務(wù)器。
解決方案:
1.我客戶端干脆不驗證,管你是不是真實的目標(biāo)網(wǎng)站。這種解決方案是網(wǎng)上最流行的解決方式
2.下載目標(biāo)網(wǎng)站證書后驗證唄
3.安裝requests的security 版本
pip3 install requests[security ]
解決方案1:不驗證
將verify=False即可,但會出現(xiàn)警告,可以使用requests.packages.urllib3.disable_warnings() 禁用警告
import requests headers = { 'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/59.0' } r = requests.get('https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx', verify= False) print(r.status_code)

解決方案2:下載目標(biāo)網(wǎng)站驗證
將目標(biāo)網(wǎng)站的證書導(dǎo)出保存起來,如圖所示:

代碼如下:
import requests REQUESTS_CA_BUNDLE= r'e:/certificate/-pheorguk.crt' headers = { 'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/59.0' } r = requests.get('https://hcaidcs.phe.org.uk/WebPages/GeneralHomePage.aspx', verify= REQUESTS_CA_BUNDLE) print(r.status_code)
運行結(jié)果:200 沒有任何錯誤及警告

解決方案3:直接安裝安全版的requests,可以有效避免
pip3 install requests[security ]
來源:https://zhuanlan.zhihu.com/p/64233102/?utm_id=0