文章目錄
一、什么是appid、appkey、appsecret
二、云服務AppId或AppKey和AppSecret生成策略
三、API接口開發安全性
四、基于AccessToken方式實現API設計
五、常見問題總結
做API接口,為什么access_token要放在Header頭里傳遞?
六、參考
一、什么是appid、appkey、appsecret
AppID:應用的唯一標識AppKey:公匙(相當于賬號)AppSecret:私匙(相當于密碼)
token:令牌(過期失效)
app_id 是用來標記你的開發者賬號的, 是你的用戶id, 這個id 在數據庫添加檢索, 方便快速查找。
app_key 和 app_secret 是一對出現的賬號, 同一個 app_id 可以對應多個 app_key+app_secret, 這樣 平臺就可以分配你不一樣的權限, 比如 app_key1 + app_secect1 只有只讀權限 但是 app_key2+app_secret2 有讀寫權限… 這樣你就可以把對應的權限 放給不同的開發者. 其中權限的配置都是直接跟app_key 做關聯的, app_key 也需要添加數據庫檢索, 方便快速查找。
至于為什么 要有app_key + app_secret 這種成對出現的機制呢, 因為 要加密, 通常 在首次驗證(類似登錄場景) , 你需要用 app_key(標記要申請的權限有哪些) + app_secret(密碼, 表示你真的擁有這個權限) 來申請一個token, 就是我們經常用到的 access_token, 之后的數據請求, 就直接提供access_token 就可以驗證權限了.
簡化的場景:
省去 app_id, 他默認每一個用戶有且僅有一套權限配置, 所以直接將 app_id = app_key , 然后外加一個app_secret就夠了.
省去app_id 和 app_key, 相當于 app_id = app_key = app_secret, 通常用于開放性接口的地方, 特別是很多地圖類api 都采用這種模式, 這種模式下, 帶上app_id 的目的僅僅是統計 某一個用戶調用接口的次數而已了.
使用方法
向第三方服務器請求授權時,帶上AppKey和AppSecret(需存在服務器端)
第三方服務器驗證AppKey和AppSecret在DB中有無記錄
如果有,生成一串唯一的字符串(token令牌),返回給服務器,服務器再返回給客戶端
客戶端下次請求敏感數據時帶上令牌
二、云服務AppId或AppKey和AppSecret生成策略
[推薦]云服務AppId或AppKey和AppSecret生成策略
參考URL: https://www.cnblogs.com/owenma/p/11419341.html
Java 原生的UUID為36位 or 32位,太長。參考原博文,分析算法:
關于appid生成:
首先,它先獲取,32個(去掉了-)十六進制字符串。
String uuid = UUID.randomUUID().toString().replace("-", "");
1
將其分成8組,每4個字符為一組str,如下16進制字符串轉10進制int型
int x = Integer.parseInt(str, 16);
1
然后通過模62操作,結果作為索引取出字符,
chars[x % 0x3E]
1
這里x % 0x3E 不好理解,其實Integer.parseInt(“3E”, 16); 結果是62,所以這里x % 0x3E就是x模62(x % 62),根據模的結果在你的定義的62個可見字符數組中取對應索引的字符。
這樣總共8組,一組取一個字符,8組取8個字符,就是你要的appid。
個人對該算法思考:它其實就是利用uuid的字符串,分成8組,做隨機數模62,感覺uuid的作用就是隨機數的作用。那么問題就是,uuid分成的8組每組真正都隨機么?假如隨機,那么我們為什么不直接生成隨機數,生成8組,為什么要用uuid呢?還是說都是造隨機兩個沒有什么本質區別,都可以,只是作者使用了uuid來造而已?
如果有算法愛好者,希望可以解答!
關于appsecrect,文章中是appid+固定字符串做sha1,感覺這樣有安全風險,別人知道appid知道算法,就可以計算出你的appsecrect。如下,個人改成了 sha1(appid + uuid)生成secrect。
/**
-
隨機產生唯一的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思想其實借鑒微博短域名的生成方式,但是其重復概率過高,而且每次生成4個,需要隨即選取一個。
- 本算法利用62個可打印字符,通過隨機生成32位UUID,由于UUID都為十六進制,
- 所以將UUID分成8組,每4個為一組,然后通過模62操作,結果作為索引取出字符,
- 這樣重復率大大降低。
- 經測試,在生成一千萬個數據也沒有出現重復,完全滿足大部分需求。
- </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接口開發安全性
[推薦]API接口安全性設計
參考URL: http://www.lxweimin.com/p/c6518a8f4040
接口的安全性主要圍繞token、timestamp和sign三個機制展開設計,保證接口的數據不會被篡改和重復調用,下面具體來看:
Token授權機制
用戶使用用戶名密碼登錄后服務器給客戶端返回一個Token(通常是UUID),并將Token-UserId以鍵值對的形式存放在緩存服務器中。服務端接收到請求后進行Token驗證,如果Token不存在,說明請求無效。Token是客戶端訪問服務端的憑證。
時間戳超時機制
用戶每次請求都帶上當前時間的時間戳timestamp,服務端接收到timestamp后跟當前時間進行比對,如果時間差大于一定時間(比如5分鐘),則認為該請求失效。時間戳超時機制是防御DOS攻擊的有效手段。
簽名機制
將 Token 和 時間戳 加上其他請求參數再用MD5或SHA-1算法(可根據情況加點鹽)加密,加密后的數據就是本次請求的簽名sign,服務端接收到請求后以同樣的算法得到簽名,并跟當前的簽名進行比對,如果不一樣,說明參數被更改過,直接返回錯誤標識。簽名機制保證了數據不會被篡改。
拒絕重復調用(非必須)
客戶端第一次訪問時,將簽名sign存放到緩存服務器中,超時時間設定為跟時間戳的超時時間一致,二者時間一致可以保證無論在timestamp限定時間內還是外 URL都只能訪問一次。如果有人使用同一個URL再次訪問,如果發現緩存服務器中已經存在了本次簽名,則拒絕服務。如果在緩存中的簽名失效的情況下,有人使用同一個URL再次訪問,則會被時間戳超時機制攔截。這就是為什么要求時間戳的超時時間要設定為跟時間戳的超時時間一致。拒絕重復調用機制確保URL被別人截獲了也無法使用(如抓取數據)。
在以上三中機制的保護下,
如果有人劫持了請求,并對請求中的參數進行了修改,簽名就無法通過;
如果有人使用已經劫持的URL進行DOS攻擊,服務器則會因為緩存服務器中已經存在簽名或時間戳超時而拒絕服務,所以DOS攻擊也是不可能的;
所有的安全措施都用上的話有時候難免太過復雜,在實際項目中需要根據自身情況作出裁剪,比如可以只使用簽名機制就可以保證信息不會被篡改,或者定向提供服務的時候只用Token機制就可以了。如何裁剪,全看項目實際情況和對接口安全性的要求~
四、基于AccessToken方式實現API設計
基于AccessToken方式實現API設計
參考URL: https://www.cnblogs.com/kevin-ying/p/10800934.html
Spring Boot入門教程(四十三): API接口設計之token、timestamp、sign
參考URL: https://blog.csdn.net/vbirdbest/article/details/80789817
需求:
A、B機構需要調用X服務器的接口,那么X服務器就需要提供開放的外網訪問接口。
分析:
1、開放平臺提供者X,為每一個合作機構提供對應的appid、app_secret。
2、appid是唯一的(不能改變),表示對應的第三方合作機構,用來區分不同機構的。
3、app_secret在傳輸中實現加密功能(秘鑰),該秘鑰可以發生改變的。
4、為什么app_secret是可以改變的?調用接口需要appid+app_secret生成對應的access_token(臨時性),如果appid和app_secret被泄密,產生安全性問題,如果一但發現被泄密,可以重新生成一個app_secret。
原理:為每個合作機構創建對應的appid、app_secret,生成對應的access_token(有效期2小時),在調用外網開放接口的時候,必須傳遞有效的access_token。
二、開發步驟
1、使用appid+app_secret生成對應的access_token
1.獲取生成的AppId和appSecret,并驗證是否可用
2.刪除之前的accessToken
3.AppId和appSecret保證生成對應唯一的accessToken
注意:以上第二步必須保證在同一事務中
4.返回最新的accessToken
2、使用accessToken調用第三方接口
1.獲取對應的accessToken
2.使用AccessToken查詢redis對應的value(appId)
3.如果沒有獲取到對應的appid,直接返回錯誤提示
4.如果能獲取到對應的appid,使用appid查詢對應的APP信息
5.使用appId查詢數據庫app信息,獲取is_flag狀態,如果為1,則不能調用接口,否則正常執行
6.直接調用接口業務
五、常見問題總結
做API接口,為什么access_token要放在Header頭里傳遞?
如果是OAuth2, 使用 Header傳遞token是屬于規范的一種,Header中有一個Authorization頭專門用于存放認證信息
每一次登錄,會生成一個新的Token, 此時舊的token并不會立即失效(取決于該token生成時,設置的失效時間)
六、參考
API接口開發安全性,你是如何解決的
參考URL: https://www.sohu.com/a/281386848_652662
[推薦]API接口安全性設計
參考URL: http://www.lxweimin.com/p/c6518a8f4040
WebApi安全性 使用TOKEN+簽名驗證
參考URL: https://www.cnblogs.com/MR-YY/p/5972380.html
云服務AppId或AppKey和AppSecret生成策略
參考URL: https://www.cnblogs.com/owenma/p/11419341.html
認識和使用JWT
參考URL: https://blog.csdn.net/qq_40493277/article/details/99626681
轉發自:https://blog.csdn.net/inthat/article/details/103140515
歡迎加 qq:2669422676 微信:13717660329 交流