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)

 

今天的普及到这里就结束啦,谢谢你们,也欢迎你们留言讨论。

相关文章
相关标签/搜索