基於http協議的api接口對於客戶端的身份認證方式以及安全措施

 由於http是無狀態的,所以正常情況下在瀏覽器瀏覽網頁,服務器都是通過訪問者的cookie(cookie中存儲的jsessionid)來辨別客戶端的身份的,當客戶端進行登錄服務器也會將登錄信息存放在服務器並與客戶端的cookie中的jsessionid關聯起來,這樣客戶端再次訪問我們就可以識別用戶身份了。

    但是對於api服務器,我們不能讓訪問者先登錄再進行訪問這樣不安全,也不友好。所以一般情況我們都是需要客戶端提供一個key(每個key跟用戶是一對一關聯的)來識別請求者的身份。

    由HTTP協議進行通信的數據大都是未經加密的明文,包括請求參數、返回值、 cookie、 head等等數據,因此,外界通過對通信的監聽,輕而易舉便可根據請求和響應雙方的格式,僞造請求與響應,修改和竊取各種信息。所以我們還需要對每次請求進行認證,來判斷髮起請求的是不是就是該用戶,以及請求信息是否被篡改。一般採用對請求信息(請求uri,參數)進行摘要的方法來解決上述問題。由於摘要算法的不可逆性,因此這種方式能夠在一定程度上防止信息被篡改,保障通信的安全。

1、MD5方式

用戶需要先在網站上申請key、secret,然後校驗流程如下:

客戶端

  1.參數排序

  2.將參數串接起來加上secret,生成待摘要字符串

  3.使用MD5等摘要算法生成摘要串signature

  4.將key,signature放入header中一併傳給服務器
服務器

  1.參數排序 

  2.將參數串接起來加上secret(通過header中的key在數據庫獲取),生成待摘要字符串 

  3.使用MD5等摘要算法生成摘要串 

  4.服務端生成的摘要串與客戶端通過header傳遞過來的摘要串進行比較

 

2、HmacSHA256方式

用戶需要先在網站上申請key、secret,然後校驗流程如下:

客戶單

  1.將請求參數封裝成json字符串,也就是請求體body

  2.使用HmacSHA256算法加secret對(請求url+nonce+body)加密生成摘要signature  

  3.將key,signature放入header中一併傳給服務器


服務器

  1.獲取請求中的請求體body字符串

  2.使用HmacSHA256算法加secret(通過header中的key在數據庫獲取)對(請求url+nonce+body)加密生成摘要signature 

  3.服務端生成的摘要串與客戶端通過header傳遞過來的摘要串進行比較

注意使用HmacSHA256更加安全,而且我們可以直接將請求參數封裝成json字符串放入請求體中(也就是通過io流)進行傳遞。


實際使用中遇到的問題:

1、帶有下劃線的header被過濾

    當我們在使用HmacSHA256進行認證的時候,需要客戶端將請求key,signature放入header,name設置爲api_key,api_signature,這時出現一個問題是服務器怎麼都獲取不到這兩個值,但是我在本機測試時沒有問題的。後來纔想起來是不是由於使用nginx做集羣而部分頭被過濾了,查看過後果然是nginx將帶有下劃線的header name過濾了,後來修改nginx配置便可以正常獲取頭信息。不過後來服務器使用了第三方的動態加速再次把帶有下劃線的header name給過濾了,爲了避免麻煩索性修改程序將header name中的下劃線都去掉了。

2、確保每次請求唯一性

    由於http都是明文請求,雖然我們可以通過摘要進行一定的安全保證確保信息不被篡改,但是我們無法保證每次請求的唯一性,也就是如果請求數據被別人獲取再次請求,此時也可能帶來很嚴重的安全性問題。於是我們便需要用戶在每次請求中設置一個遞增的參數nonce,來確保每次請求都是唯一的。不過這樣也可能帶來一個問題,就是如果用戶近乎同時發起兩個請求a b,由於網絡阻塞,可能後發起的b先到達服務器,這樣當a達到的時候,服務器會認爲a的nonce已過期請求非法而拒絕。爲了解決這樣的問題我們允許用戶設置一個expire值來避免nonce認證帶來的問題。

3、SNI

    由於當時我們有不同的工程(不同的域名,跟不同的證書)位於同一臺服務器,這樣有的客戶端訪問我們api工程會拋異常,說http握手失敗或者說請求域名與服務器證書不匹配而失敗。所以我們需要客戶端程序支持sni,它允許客戶端在發起SSL握手請求時(具體說來,是客戶端發出SSL請求中的ClientHello階段),就提交請求的Host信息,使得服務器能夠切換到正確的域並返回相應的證書。對於java語言來說jdk7的後續版本已經支持sni,或者使用httpclient 4.3及以後版本都可以很好的支持sni了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章