開放api接口平臺(tái):appid、appkey、appsecret

文章目錄
一、什么是appid、appkey、appsecret
二、云服務(wù)AppId或AppKey和AppSecret生成策略
三、API接口開發(fā)安全性
四、基于AccessToken方式實(shí)現(xiàn)API設(shè)計(jì)
五、常見問題總結(jié)
做API接口,為什么access_token要放在Header頭里傳遞?
六、參考

一、什么是appid、appkey、appsecret

AppID:應(yīng)用的唯一標(biāo)識(shí)AppKey:公匙(相當(dāng)于賬號(hào))AppSecret:私匙(相當(dāng)于密碼)

token:令牌(過期失效)

app_id 是用來標(biāo)記你的開發(fā)者賬號(hào)的, 是你的用戶id, 這個(gè)id 在數(shù)據(jù)庫添加檢索, 方便快速查找。

app_key 和 app_secret 是一對(duì)出現(xiàn)的賬號(hào), 同一個(gè) app_id 可以對(duì)應(yīng)多個(gè) app_key+app_secret, 這樣 平臺(tái)就可以分配你不一樣的權(quán)限, 比如 app_key1 + app_secect1 只有只讀權(quán)限 但是 app_key2+app_secret2 有讀寫權(quán)限… 這樣你就可以把對(duì)應(yīng)的權(quán)限 放給不同的開發(fā)者. 其中權(quán)限的配置都是直接跟app_key 做關(guān)聯(lián)的, app_key 也需要添加數(shù)據(jù)庫檢索, 方便快速查找。

至于為什么 要有app_key + app_secret 這種成對(duì)出現(xiàn)的機(jī)制呢, 因?yàn)?要加密, 通常 在首次驗(yàn)證(類似登錄場(chǎng)景) , 你需要用 app_key(標(biāo)記要申請(qǐng)的權(quán)限有哪些) + app_secret(密碼, 表示你真的擁有這個(gè)權(quán)限) 來申請(qǐng)一個(gè)token, 就是我們經(jīng)常用到的 access_token, 之后的數(shù)據(jù)請(qǐng)求, 就直接提供access_token 就可以驗(yàn)證權(quán)限了.

簡(jiǎn)化的場(chǎng)景:

省去 app_id, 他默認(rèn)每一個(gè)用戶有且僅有一套權(quán)限配置, 所以直接將 app_id = app_key , 然后外加一個(gè)app_secret就夠了.
省去app_id 和 app_key, 相當(dāng)于 app_id = app_key = app_secret, 通常用于開放性接口的地方, 特別是很多地圖類api 都采用這種模式, 這種模式下, 帶上app_id 的目的僅僅是統(tǒng)計(jì) 某一個(gè)用戶調(diào)用接口的次數(shù)而已了.
使用方法

向第三方服務(wù)器請(qǐng)求授權(quán)時(shí),帶上AppKey和AppSecret(需存在服務(wù)器端)

第三方服務(wù)器驗(yàn)證AppKey和AppSecret在DB中有無記錄

如果有,生成一串唯一的字符串(token令牌),返回給服務(wù)器,服務(wù)器再返回給客戶端

客戶端下次請(qǐng)求敏感數(shù)據(jù)時(shí)帶上令牌

二、云服務(wù)AppId或AppKey和AppSecret生成策略

[推薦]云服務(wù)AppId或AppKey和AppSecret生成策略
參考URL: https://www.cnblogs.com/owenma/p/11419341.html

Java 原生的UUID為36位 or 32位,太長(zhǎng)。參考原博文,分析算法:

關(guān)于appid生成:

首先,它先獲取,32個(gè)(去掉了-)十六進(jìn)制字符串。

String uuid = UUID.randomUUID().toString().replace("-", "");

1
將其分成8組,每4個(gè)字符為一組str,如下16進(jìn)制字符串轉(zhuǎn)10進(jìn)制int型

    int x = Integer.parseInt(str, 16);

1
然后通過模62操作,結(jié)果作為索引取出字符,

    chars[x % 0x3E]

1
這里x % 0x3E 不好理解,其實(shí)Integer.parseInt(“3E”, 16); 結(jié)果是62,所以這里x % 0x3E就是x模62(x % 62),根據(jù)模的結(jié)果在你的定義的62個(gè)可見字符數(shù)組中取對(duì)應(yīng)索引的字符。

這樣總共8組,一組取一個(gè)字符,8組取8個(gè)字符,就是你要的appid。

個(gè)人對(duì)該算法思考:它其實(shí)就是利用uuid的字符串,分成8組,做隨機(jī)數(shù)模62,感覺uuid的作用就是隨機(jī)數(shù)的作用。那么問題就是,uuid分成的8組每組真正都隨機(jī)么?假如隨機(jī),那么我們?yōu)槭裁床恢苯由呻S機(jī)數(shù),生成8組,為什么要用uuid呢?還是說都是造隨機(jī)兩個(gè)沒有什么本質(zhì)區(qū)別,都可以,只是作者使用了uuid來造而已?
如果有算法愛好者,希望可以解答!

關(guān)于appsecrect,文章中是appid+固定字符串做sha1,感覺這樣有安全風(fēng)險(xiǎn),別人知道appid知道算法,就可以計(jì)算出你的appsecrect。如下,個(gè)人改成了 sha1(appid + uuid)生成secrect。

/**

  • 隨機(jī)產(chǎn)生唯一的app_key和app_secret
    */
    public class AppUtils {

    private final static String[] chars = new String[]{"a", "b", "c", "d", "e", "f",
    "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
    "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
    "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
    "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
    "W", "X", "Y", "Z"};

    /**

    • @Description: <p>
    • 短8位UUID思想其實(shí)借鑒微博短域名的生成方式,但是其重復(fù)概率過高,而且每次生成4個(gè),需要隨即選取一個(gè)。
    • 本算法利用62個(gè)可打印字符,通過隨機(jī)生成32位UUID,由于UUID都為十六進(jìn)制,
    • 所以將UUID分成8組,每4個(gè)為一組,然后通過模62操作,結(jié)果作為索引取出字符,
    • 這樣重復(fù)率大大降低。
    • 經(jīng)測(cè)試,在生成一千萬個(gè)數(shù)據(jù)也沒有出現(xiàn)重復(fù),完全滿足大部分需求。
    • </p>
      */
      public static String getAppId() {
      StringBuffer shortBuffer = new StringBuffer();
      String uuid = UUID.randomUUID().toString().replace("-", "");
      for (int i = 0; i < 8; i++) {
      String str = uuid.substring(i * 4, i * 4 + 4);
      int x = Integer.parseInt(str, 16);
      shortBuffer.append(chars[x % 0x3E]);
      }
      return shortBuffer.toString();

    }

    /**

    • 算法: sha1(appid+uuid) 生成AppSecret
      */
      public static String getAppSecret(String appId) {
      try {
      StringBuffer sb = new StringBuffer();
      String uuid = UUID.randomUUID().toString();

      sb.append(appId).append(uuid);
      
      String str = sb.toString();
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(str.getBytes());
      byte[] digest = md.digest();
      
      StringBuffer hexstr = new StringBuffer();
      String shaHex = "";
      for (int i = 0; i < digest.length; i++) {
          shaHex = Integer.toHexString(digest[i] & 0xFF);
          if (shaHex.length() < 2) {
              hexstr.append(0);
          }
          hexstr.append(shaHex);
      }
      return hexstr.toString();
      

      } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      }
      return appId;
      }

    public static void main(String[] args) {
    String appId = getAppId();
    String appSecret = getAppSecret(appId);
    System.out.println("appId: "+appId);
    System.out.println("appSecret: "+appSecret);
    }
    }

三、API接口開發(fā)安全性

[推薦]API接口安全性設(shè)計(jì)
參考URL: http://m.itdecent.cn/p/c6518a8f4040

接口的安全性主要圍繞token、timestamp和sign三個(gè)機(jī)制展開設(shè)計(jì),保證接口的數(shù)據(jù)不會(huì)被篡改和重復(fù)調(diào)用,下面具體來看:

Token授權(quán)機(jī)制
用戶使用用戶名密碼登錄后服務(wù)器給客戶端返回一個(gè)Token(通常是UUID),并將Token-UserId以鍵值對(duì)的形式存放在緩存服務(wù)器中。服務(wù)端接收到請(qǐng)求后進(jìn)行Token驗(yàn)證,如果Token不存在,說明請(qǐng)求無效。Token是客戶端訪問服務(wù)端的憑證。

時(shí)間戳超時(shí)機(jī)制
用戶每次請(qǐng)求都帶上當(dāng)前時(shí)間的時(shí)間戳timestamp,服務(wù)端接收到timestamp后跟當(dāng)前時(shí)間進(jìn)行比對(duì),如果時(shí)間差大于一定時(shí)間(比如5分鐘),則認(rèn)為該請(qǐng)求失效。時(shí)間戳超時(shí)機(jī)制是防御DOS攻擊的有效手段。

簽名機(jī)制
將 Token 和 時(shí)間戳 加上其他請(qǐng)求參數(shù)再用MD5或SHA-1算法(可根據(jù)情況加點(diǎn)鹽)加密,加密后的數(shù)據(jù)就是本次請(qǐng)求的簽名sign,服務(wù)端接收到請(qǐng)求后以同樣的算法得到簽名,并跟當(dāng)前的簽名進(jìn)行比對(duì),如果不一樣,說明參數(shù)被更改過,直接返回錯(cuò)誤標(biāo)識(shí)。簽名機(jī)制保證了數(shù)據(jù)不會(huì)被篡改。

拒絕重復(fù)調(diào)用(非必須)
客戶端第一次訪問時(shí),將簽名sign存放到緩存服務(wù)器中,超時(shí)時(shí)間設(shè)定為跟時(shí)間戳的超時(shí)時(shí)間一致,二者時(shí)間一致可以保證無論在timestamp限定時(shí)間內(nèi)還是外 URL都只能訪問一次。如果有人使用同一個(gè)URL再次訪問,如果發(fā)現(xiàn)緩存服務(wù)器中已經(jīng)存在了本次簽名,則拒絕服務(wù)。如果在緩存中的簽名失效的情況下,有人使用同一個(gè)URL再次訪問,則會(huì)被時(shí)間戳超時(shí)機(jī)制攔截。這就是為什么要求時(shí)間戳的超時(shí)時(shí)間要設(shè)定為跟時(shí)間戳的超時(shí)時(shí)間一致。拒絕重復(fù)調(diào)用機(jī)制確保URL被別人截獲了也無法使用(如抓取數(shù)據(jù))。

在以上三中機(jī)制的保護(hù)下,

如果有人劫持了請(qǐng)求,并對(duì)請(qǐng)求中的參數(shù)進(jìn)行了修改,簽名就無法通過;

如果有人使用已經(jīng)劫持的URL進(jìn)行DOS攻擊,服務(wù)器則會(huì)因?yàn)榫彺娣?wù)器中已經(jīng)存在簽名或時(shí)間戳超時(shí)而拒絕服務(wù),所以DOS攻擊也是不可能的;

所有的安全措施都用上的話有時(shí)候難免太過復(fù)雜,在實(shí)際項(xiàng)目中需要根據(jù)自身情況作出裁剪,比如可以只使用簽名機(jī)制就可以保證信息不會(huì)被篡改,或者定向提供服務(wù)的時(shí)候只用Token機(jī)制就可以了。如何裁剪,全看項(xiàng)目實(shí)際情況和對(duì)接口安全性的要求~

四、基于AccessToken方式實(shí)現(xiàn)API設(shè)計(jì)

基于AccessToken方式實(shí)現(xiàn)API設(shè)計(jì)
參考URL: https://www.cnblogs.com/kevin-ying/p/10800934.html
Spring Boot入門教程(四十三): API接口設(shè)計(jì)之token、timestamp、sign
參考URL: https://blog.csdn.net/vbirdbest/article/details/80789817

需求:

A、B機(jī)構(gòu)需要調(diào)用X服務(wù)器的接口,那么X服務(wù)器就需要提供開放的外網(wǎng)訪問接口。

分析:

1、開放平臺(tái)提供者X,為每一個(gè)合作機(jī)構(gòu)提供對(duì)應(yīng)的appid、app_secret。

2、appid是唯一的(不能改變),表示對(duì)應(yīng)的第三方合作機(jī)構(gòu),用來區(qū)分不同機(jī)構(gòu)的。

3、app_secret在傳輸中實(shí)現(xiàn)加密功能(秘鑰),該秘鑰可以發(fā)生改變的。

4、為什么app_secret是可以改變的?調(diào)用接口需要appid+app_secret生成對(duì)應(yīng)的access_token(臨時(shí)性),如果appid和app_secret被泄密,產(chǎn)生安全性問題,如果一但發(fā)現(xiàn)被泄密,可以重新生成一個(gè)app_secret。

原理:為每個(gè)合作機(jī)構(gòu)創(chuàng)建對(duì)應(yīng)的appid、app_secret,生成對(duì)應(yīng)的access_token(有效期2小時(shí)),在調(diào)用外網(wǎng)開放接口的時(shí)候,必須傳遞有效的access_token。

二、開發(fā)步驟

1、使用appid+app_secret生成對(duì)應(yīng)的access_token

1.獲取生成的AppId和appSecret,并驗(yàn)證是否可用
2.刪除之前的accessToken
3.AppId和appSecret保證生成對(duì)應(yīng)唯一的accessToken
注意:以上第二步必須保證在同一事務(wù)中
4.返回最新的accessToken

2、使用accessToken調(diào)用第三方接口

1.獲取對(duì)應(yīng)的accessToken
2.使用AccessToken查詢r(jià)edis對(duì)應(yīng)的value(appId)
3.如果沒有獲取到對(duì)應(yīng)的appid,直接返回錯(cuò)誤提示

4.如果能獲取到對(duì)應(yīng)的appid,使用appid查詢對(duì)應(yīng)的APP信息
5.使用appId查詢數(shù)據(jù)庫app信息,獲取is_flag狀態(tài),如果為1,則不能調(diào)用接口,否則正常執(zhí)行
6.直接調(diào)用接口業(yè)務(wù)

五、常見問題總結(jié)

做API接口,為什么access_token要放在Header頭里傳遞?
如果是OAuth2, 使用 Header傳遞token是屬于規(guī)范的一種,Header中有一個(gè)Authorization頭專門用于存放認(rèn)證信息
每一次登錄,會(huì)生成一個(gè)新的Token, 此時(shí)舊的token并不會(huì)立即失效(取決于該token生成時(shí),設(shè)置的失效時(shí)間)

六、參考

API接口開發(fā)安全性,你是如何解決的
參考URL: https://www.sohu.com/a/281386848_652662
[推薦]API接口安全性設(shè)計(jì)
參考URL: http://m.itdecent.cn/p/c6518a8f4040
WebApi安全性 使用TOKEN+簽名驗(yàn)證
參考URL: https://www.cnblogs.com/MR-YY/p/5972380.html
云服務(wù)AppId或AppKey和AppSecret生成策略
參考URL: https://www.cnblogs.com/owenma/p/11419341.html
認(rèn)識(shí)和使用JWT
參考URL: https://blog.csdn.net/qq_40493277/article/details/99626681

轉(zhuǎn)發(fā)自:https://blog.csdn.net/inthat/article/details/103140515

歡迎加 qq:2669422676 微信:13717660329 交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容