App開放接口api安全性—Token簽名sign的設計與實現

前言

在app開放接口api的設計中,避免不了的就是安全性問題,由於大多數接口涉及到用戶的我的信息以及一些敏感的數據,因此對這些 接口須要進行身份的認證,那麼這就須要用戶提供一些信息,好比用戶名密碼等,可是爲了安全起見讓用戶暴露的明文密碼次數越少越好,咱們通常在web項目 中,大多數採用保存的session中,而後在存一份到cookie中,來保持用戶的回話有效性。可是在app提供的開放接口中,後端服務器在用戶登陸後 如何去驗證和維護用戶的登錄有效性呢,如下是參考項目中設計的解決方案,其原理和大多數開放接口安全驗證同樣,如淘寶的開放接口token驗證,微信開發 平臺token驗證都是同理。

html

簽名設計

對於敏感的api接口,需使用https協議

https是在http超文本傳輸協議加入SSL層,它在網絡間通訊是加密的,因此須要加密證書。

https協議須要ca證書,通常須要交費。

web

簽名的設計

原理:用戶登陸後向服務器提供用戶認證信息(如帳戶和密碼),服務器認證完後給客戶端返回一個Token令牌,用戶再次獲取信息時,帶上此令牌,若是令牌正取,則返回數據。對於獲取Token信息後,訪問用戶相關接口,客戶端請求的url須要帶上以下參數:

時間戳:timestamp

Token令牌:token

而後將全部用戶請求的參數按照字母排序(包括timestamp,token),而後更具MD5加密(能夠加點鹽),所有大寫,生成sign簽名,這就是 所說的url簽名算法。而後登錄後每次調用用戶信息時,帶上sign,timestamp,token參數。

例如:原請求https://www.andy.cn/api/user/update/info.shtml?city=北京 (post和get都同樣,對全部參數排序加密)

加上時間戳和token

https://www.andy.cn/api/user/update/info.shtml?city=北京×tamp=12445323134&token=wefkfjdskfjewfjkjfdfnc
而後更具url參數生成sign

最終的請求如

https://www.andy.cn /api/user/update/info.shtml?city=北京×tamp=12445323134& token=wefkfjdskfjewfjkjfdfnc&sign=FDK2434JKJFD334FDF2
其最終的原理是減少明文的暴露次數;保證數據安全的訪問。

具體實現以下:

1. api請求客戶端想服務器端一次發送用用戶認證信息(用戶名和密碼),服務器端請求到改請求後,驗證用戶信息是否正確。

若是正確:則返回一個惟一不重複的字符串(通常爲UUID),而後在Redis(任意緩存服務器)中維護Token----Uid的用戶信息關係,以便其餘api對token的校驗。

若是錯誤:則返回錯誤碼。



2.服務器設計一個url請求攔截規則

(1)判斷是否包含timestamptokensign參數,若是不含有返回錯誤碼。

(2)判斷服務器接到請求的時間和參數中的時間戳是否相差很長一段時間(時間自定義如半個小時),若是超過則說明該 url已經過時(若是url被盜,他改變了時間戳,可是會致使sign簽名不相等)。

(3)判斷token是否有效,根據請求過來的token,查詢redis緩存中的uid,若是獲取不到這說明該token已過時

(4)根據用戶請求的url參數,服務器端按照一樣的規則生成sign簽名,對比簽名看是否相等,相等則放行。(天然url簽名 也沒法100%保證其安全,也能夠經過公鑰AES對數據和url加密,但這樣若是沒法確保公鑰丟失,因此簽名只是很大程 度上保證安全)。

(5)此url攔截只需對獲取身份認證的url放行(如登錄url),剩餘全部的url都需攔截。

3.Token和Uid關係維護

對於用戶登陸咱們須要建立token--uid的關係,用戶退出時須要需刪除token--uid的關係。

redis

簽名實現

獲取所有請求參數算法

複製代碼
String sign = request.getParameter("sign");
        Enumeration<?> pNames =  request.getParameterNames();
        Map<String, Object> params = new HashMap<String, Object>();
        while (pNames.hasMoreElements()) {
            String pName = (String) pNames.nextElement();
            if("sign".equals(pName))continue;
            Object pValue = request.getParameter(pName);
            params.put(pName, pValue);
        }
複製代碼


生成簽名

後端

複製代碼
public static String createSign(Map<String, String> params, boolean encode)
            throws UnsupportedEncodingException {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuffer temp = new StringBuffer();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = String.valueOf(value);
            }
            if (encode) {
                temp.append(URLEncoder.encode(valueString, "UTF-8"));
            } else {
                temp.append(valueString);
            }
        }

        return MD5Utils.getMD5(temp.toString()).toUpperCase();
    }
複製代碼

轉載 http://www.lai18.com/content/944366.htmlapi

http://www.cnblogs.com/whcghost/p/5657594.html跨域

 

傳統身份驗證方法瀏覽器

Cookie驗證是一種比較傳統的HTTP安全策略。Cookie驗證機制就是爲一次請求認證在服務端建立一個Session對象,同時在客戶端的瀏覽器端建立了一個Cookie對象;經過客戶端帶上來Cookie對象來與服務器端的Session對象匹配來實現狀態管理的。
默認的,當咱們關閉瀏覽器的時候,cookie會被刪除。但能夠經過修改cookie 的過時時間使Cookie在必定時間內有效。緩存

基於 Token 的身份驗證方法

使用基於Token的身份驗證方法,在服務端不須要存儲用戶的登陸記錄。基本流程以下:安全

(1)客戶端使用用戶名密碼請求登陸;

(2)服務端收到請求,驗證用戶名與密碼。驗證成功服務端簽發一個Token,再把這個Token發送給客戶端;

(3)客戶端每次向服務端發起請求,都須要帶着服務端最新簽發的Token;

(4)服務端收到請求,驗證請求裏面的Token,若是驗證成功返回請求的數據。流程圖以下:


Token身份驗證的優點

(1)支持跨域訪問:Cookie是不容許垮域訪問的,這一點對Token機制是不存在的,前提是傳輸的用戶認證信息經過HTTP頭傳輸;(2)更適用CDN:能夠經過內容分發網絡請求你服務端的全部資料,而你的服務端只要提供API便可;(3)去耦:不須要綁定到一個特定的身份驗證方案。Token能夠在任何地方生成,只要在你的API被調用的時候,你能夠進行Token生成調用便可;(4)更適用於移動應用:若是客戶端是一個原平生臺(好比 iOS,Android,Windows 8 等),是不支持Cookie的,須要額外經過Cookie容器進行處理,這時採用Token驗證機制就會簡單得多。

相關文章
相關標籤/搜索