1. 程式人生 > >RESTful介面簽名認證實現機制

RESTful介面簽名認證實現機制

RESTful介面

       網際網路發展至今,催生出了很多豐富多彩的應用,極大地調動了人們對這些應用的使用熱情。但同時也為網際網路應用帶來了嚴峻的考驗。具體體現在以下幾個方面:

1.     部署方式的改變:當用戶量不多的情況下,可能只需部署一臺伺服器就可以解決問題,但是當很多使用者的情況下,為抗住高併發訪問,需要組成應用叢集對外提供服務;

2.     應用構建的改變:很多應用採用了多種技術解決方案,不同程式語言(如C,Java,Python),所以很難採用傳統應用構建模式將不同模組整合進來;

3.     資料開放的改變:開放是網際網路發展的必然,因為這種方式將應用本身的價值最大化了,同時使用者可以基於已有功能生成特有需求應用,提高使用者粘度,開放共贏。

而近觀傳統的Web應用,均為採用集中部署結構,基於某種特定技術開發完成,基於session或cookie等會話追蹤機制。加上需要系統間互動資訊,使得實現十分複雜,且可伸縮性、易用性、維護性極差。

       基於以上矛盾,出現了一種新的網際網路應用架構風格—REST(Representational StateTransfer)。最初這種思路出現在Roy Fielding博士的論文中,他也是HTTP規範的主要作者之一。REST充分利用HTTP的優勢,以資源位核心,將資源的CRUD對映為HTTP的GET PUT POST DELTE方法,服務端無需儲存任何客戶端資訊。客戶端的每次資源請求包含了服務端響應需要的所有語義資訊。

       我們可以看出,基於REST風格架構的應用特點是:網際網路可以看成一個巨大的狀態機,資源相當於狀態,而URI相當於狀態的表述。客戶端通過訪問不同資源,進行狀態切換。服務端卻無須記住這些狀態,可通過橫向擴充套件方式消除效能瓶頸。

       但是,REST構建的應用如何進行安全控制呢?我們可不希望把自己暴露出去任人“宰割”。目前,常用的方式是OAUTH形式認證方式,這種方式適合對其他應用系統有很強依賴的時候考慮,比如新浪微博開放介面就採用這種。本文主要講解基於token機制的簽名認證模式。

具體簽名規則

       在使用者可以使用REST介面之前,首先需要通過向REST介面開放方申請,當獲准後會收到兩個key:accessKey和secretKey。其中accessKey相當於使用者標識,應用會通過它區分不同使用者,而secreKey相當於提供給使用者的密碼,在介面使用過程中都不會在網路中傳輸,只有使用者和應用系統知道。

       使用者對介面的每一次請求都會預設通過某種機制生成一個簽名,然後傳送給REST服務端。服務端收到後,會根據該機制驗證該請求的合法性,從而避免非法使用者的隨意使用。

       一般,簽名以如下形式儲存在HTTP Header中傳送給REST伺服器(其中oss為固定字,Signature是摘要內容):

token = “oss” + “ ”+ accessKey + “:” + Signature

       計算的虛擬碼如下:

StringToSing =HTTP-Verb +”\n”+      //http請求的動作

            Content-MD5+”\n”+     //http請求的MD5值

            Content-Type+”\n”+     //http請求的型別

            Date+”\n”+            //http請求時間

            CanonicalizdResource;  //http請求資源

       其中HTTP-Verb是http請求動作,對應於GET,PUT,DELETE,POST等(不能為空),Content-MD5表示請求內容資料的MD5值(可以為空,以空字元代替,下同),Content-Type為請求的型別(可以為空),Date為本次操作的時間(不能為空),CanonicalizdResource表示請求的資源(不能為空),當然我們還可以根據系統本身情況指定某些可選或必選引數。

       Signature =BASE64(HMAC-SHA1(UTF-8-Encoding-Of(secretKey, StringToSign)))

採用utf-8提前對引數進行編碼,可以減少客戶端編碼差異帶來的影響,因為服務端到時是統一採用utf-8來做的,HMAC-SHA1生成簽名摘要指紋資訊是不可逆的,安全性得到提高,最後還進行了BASE64編碼的原因是將摘要內容全部轉換為可顯字元,應對某些不可顯字元在網路傳輸中的丟失。

       服務端驗證方式則是根據傳輸過來的token解析出accessKey和Singature,根據accessKey得到本地儲存的對應secretKey(注意其並未在網路中傳輸),然後再重新根據客戶端Signature生成方式重新生成與解析的進行比較,相同則認證成功結束,否則,直接返回錯誤資訊給客戶端。

       整個流程通過以下一張圖,進一步闡述:

       值得注意的是,JDK提供了java.securty包,裡面有各種加密演算法,用來進行程式碼的標識和身份認證。

術語解釋

       接下來簡要的對常用的摘要演算法及加密演算法進行解釋,方便具體使用過程中採取不同方式加強系統的安全性。

       常用的雜湊演算法(生成指紋或簽名)有MD5和SHA。MD5在檔案完整性、網站登入和數字簽名等領域有著廣泛使用,理論上說MD5數字簽名可以偽造,但說其已被破解,那只是杞人憂天罷了。SHA也是著名的雜湊演算法,不可逆演算法,多用於數字簽名的情況。

       常用的對稱加密演算法有DES和AES。DES是老牌的加密演算法,這是應用最廣泛的金鑰系統,也是可逆的對稱加密演算法。而AES是一種高階的加密標準,2002年成為標準,可用於替代DES,可逆對稱加密演算法。

       常用的非對稱公鑰加密演算法是RSA,多數網銀採用的就是RSA演算法來認證的。RSA的安全性依賴於大數的因子分解,它是第一個技能用於資料加密也能用於數字簽名的演算法,也是可逆演算法。但是注意這種演算法運算代價很高,速度比較慢,比DES之類演算法要慢得多。

       對於RSA囉嗦下,公鑰和私鑰成對出現。用公鑰加密資料,用私鑰解密資料(別人傳資料給我);用私鑰加密資料作為數字簽名,用公鑰來驗證數字簽名(我傳資料給別人)。