咱們作的產品是To B的,那麼咱們自身會有一個雲運營平臺的系統,這個系統包含咱們全部項目的運營管理數據,在一個月前,咱們還不須要想對外提供服務,可是有一天咱們數據被其餘團隊所須要了,需求就來了?算法
需求:咱們要作一個接口認證,用來識別對方服務是啥?安全
小A同窗領到任務開始是很開心的,立馬作了好幾個方案給領導審閱。bash
約定client的token值爲12345678,
那麼請求的url地址爲:
/remote/getApk?token=12345678
服務端接收到token後,進行匹配判斷是否合法token,不合法就退出,合法就是後續操做。
複製代碼
簡單,很是簡單,調用方直接拿到這個token寫入header頭部或者url,在服務端拿到後進行簡單匹配邏輯來肯定調用方是否正確,就完事了,從明面上來說,這個已經知足需求了,可是新的問題來了?服務器
若是我這個token被第三方截取怎麼辦?網絡
答: 上https,安全ui
沒毛病的,https是安全,由於在http協議的基礎上增長一層SSL/TLS(能夠理解爲http是裸奔,SSL/TLS 是盔甲,遮蓋住重要的信息),可是在咱們這小門小戶要實現所有https不太可能,並且https對於客戶端的調用也不是那麼方便,那麼接下來又怎麼辦呢?加密
其實這裏根本不須要加參數,服務端默認就能夠獲取客戶端的ip,這就保證一點,若是咱們token被劫持,就算給你發,也沒啥用,沒錯,在不少內部系統中,咱們設計接口校驗就算基於它來作的,由於這個更簡單,基本兩邊接口徹底不須要改東西,寫完就能夠調,就一個ip白名單配置。url
那有沒有可能這個包被別人劫持,而後進行ip代理,而後來請求呢?spa
前提:設計
這裏約定就不是token了,使用一個雙方約定的密碼鹽值salt=123456
GET /remote/getApk?md5=043c00e6c7ff021e8cc4d394d3264cb5&sign=md5(043c00e6c7ff021e8cc4d394d3264cb5+123456)
sign 計算方式:將咱們請求的參數按key的正序排序,把裏面的值進行字符串鏈接而且加上salt,再進行一個md5計算,固然能夠選擇其餘hash算法,例如sha1等
複製代碼
這種方案在服務端,咱們同樣實現這一算法,而且最終校驗這個sign值是否同樣,固然這個方案並不能解決咱們剛剛一開始說不安全的問題,由於網絡截取是個很日常的事情。
那麼有沒有辦法截取了用不了呢?
答案是確定的,那咱們在url地址添加一個請求的時間戳
GET /remote/getApk?t=1561969549&md5=043c00e6c7ff021e8cc4d394d3264cb5&sign=md5(043c00e6c7ff021e8cc4d394d3264cb5+1561969549+123456)
sign 計算方式:將咱們請求的參數按key的正序排序,把裏面的值進行字符串鏈接而且加上salt,再進行一個md5計算,固然能夠選擇其餘hash算法,例如sha1等
複製代碼
這裏是加一個時間戳做爲sign的參數,那麼能夠理解爲這個sign值是在特定時間內有效,在服務端接收到請求後,能夠優先判斷時間戳與服務端時間偏移,若是在一分鐘以內,那麼這個都是能夠請求,超過說明這個已通過期了
若是咱們對於接口請求嚴格限制,那麼咱們每次請求過的sign值不能重複,這個涉及到另外話題:
能夠簡單說一下:咱們能夠將每一個時間戳創建一個桶,每一個桶裏面裝的就是這些sign值,這些時間戳的過時時間與服務端判斷的過時時間一致(若是t字段過時,那麼就走不到這一步),就是這麼簡單哈。
看到這裏有同窗確定會問:時間戳不同咋辦,客戶端與服務端時間戳確定會不同的?
能想到這的同窗,真的很是聰明,由於是真的有這個問題出現,固然不是這個場景,只要是時間區間判斷的問題,都要考慮雙方時間戳的問題
其實這個方案設計是僅限於咱們企業內部服務相互調用的一個接口設計,剛開始接到任務都會想jwt oauth2.0等方案,後來仔細想一想,咱們壓根不須要那麼複雜的邏輯來作,由於咱們面向的是服務,不是面向獨立個體的用戶,固然用jwt和oauth2.0也能夠,就是咱們接口的請求調用就變成登陸、校驗、鑑權 等方式了。
謝謝各位同窗查閱