API 接口設計中 Token 類型的分類與設計

 

在實際的網站設計中咱們常常會遇到用戶數據的驗證和加密的問題,若是實現單點,若是保證數據準確,如何放着重放,如何防止CSRF等等前端

 

其中,在全部的服務設計中,都不可避免的涉及到Token的設計。算法

 

目前,基於Token的生成方,咱們把Token生成分爲兩種類型。api

一、基於用戶/網站,可見的加密請求方式服務器

二、基於服務器間通信的不可見加密請求方式(API Token)session

 

其中,網頁/APP訪問又分爲 登陸態和非登陸態 兩種請求區別。app

(非登陸態請求要求用戶訪問頁面時會隨機生成惟一且有時效性的token,該token在每次請求時都是不一樣)網站

(登陸狀態中,token會保存必定的時間,頁面中的token會做爲用戶身份識別)加密

 

雖然說二者做用有必定的區別,可是實現的原理是相同的。spa

 

一、非登陸狀態設計

 

原理:

 

非登陸狀態中,防止服務器資源被重複利用,咱們在前端頁面中會添加一步創建初始Session的過程,該過程來確保下一步關鍵請求不被利用。

通常這種驗證方式用於體驗頁面,如:視頻播放頁面,項目或功能展現頁面等

 

優勢:

目的就是有點,防止token被盜用,重複請求服務器資源(相似於抖音視頻播放時的簽名算法做用)

 

缺點:

全部前端加密都有被破解的可能,須要對具體的JS進行混淆,同時添加https和來源判斷

 

二、登陸狀態

 

 登陸狀態的Token

 

登陸態token 經過服務器生成:

Encode(MD5({session}+{用戶信息摘要}+{Timestamp})+TimeStamp)

  

聯合Redis 刷新用戶登陸時長及token有效時長。Redis設置自動過時時間。

驗證方法:

decode(Token)->sign+TimeStamp

 

if(sign===MD5({session}+{用戶信息摘要}+{Timestamp})){
  // XXXX
}

 

(防止弱語言的判斷邏輯,驗證PW和Token要用=== 強類型判斷)

 

退出登陸:刪除Redis 鍵值

單點登陸:從新登陸時信息更新,用戶信息摘要不變,自動刷新Redis的Token值和有效期

 

三、API 非對稱加密

api的非對稱加密經常使用於服務器之間的請求,雙方各自保存私鑰和公鑰。API接口中常體現於【APP_ID,APP_KEY|APP_SECRET】

 

Token 生成算法:

    /**
     * 生成token
     * @param $user_info string 
     * @param $app_key string  app_key
     * @param $app_id int app_id
     * @return string
     */
    public function generate_access_token($user_info , $app_key, $app_id)
    {
        $time = time();
        $sign = sha1($time . $advertiser_id . $app_key);
        $token = base64_encode("{$time},{$user_info },{$app_id},{$sign}");
        return $token;
    }

 

Token解析方法:

解密的方法中對時效性作了一分鐘的驗證,實際項目中能夠根據狀況開放失效的設置。

    /**
     * 解析token
     * @param $access_token
     * @return array
     */
    public function analysis_access_token($access_token)
    {

        $token_array = base64_decode($access_token);
        $token_array = explode(',', $token_array);
        $time = $token_array[0];
        $user_info = $token_array[1];
        $app_id = $token_array[2];
        $sign = $token_array[3];

        if ($time < (time() - 60) || $time > (time() + 60)) {
            call_back(1101, 'Access Token expire !token=' . $access_token);
        }

        global $third_platform_app_key;// app_id-app_key對應表

        if (!isset($third_platform_app_key[$app_id])) {
            call_back(1101, 'Access Token App id Error!token=' . $access_token);
        }

        $app_key = $third_platform_app_key[$app_id];

        $local_sign = sha1($time . $user_info . $app_key);

        if ($local_sign === $sign) {
            return [
                'access_token' => $access_token,
                'user_info' => $user_info,
                'time' => $time,
                'app_id' => $app_id,
                'app_key' => $app_key,
            ];
        } else {
            call_back(1101, 'Access Token Sign Error!token=' . $access_token);
        }
    }

 

 改Token方式要求每次請求都須要生成新的token來確保請求的時效性

 

另外:爲了增強API接口請求的完整性,咱們也會對請求內容進行字段排序後摘要驗證。(詳情參考:https://open.taobao.com/docV2.htm?docId=101617&docType=1)

 

今天的普及到這裏就結束啦,謝謝你們,也歡迎你們留言討論。

相關文章
相關標籤/搜索