
關于API令牌你需要知道的一切
正是因為是簡單的base64編碼存儲,切記切記在這種方式下一定得注意使用ssl,不然就是裸奔了。 在某些產品中也是基于這種類似方式,只是沒有使用apache的basic機制,而是自己寫了認證框架,原理還是一樣的,在一次請求中base64解碼Authorization字段,再和認證信息做校驗。很顯然這種方式有問題,認證信息相當于明文傳輸,另外也沒有防暴力破解功能。
API Key就是經過用戶身份認證之后服務端給客戶端分配一個API Key,類似:http://example.com/api?key=dfkaj134,一般的處理流程如下: 一個簡單的設計示例如下: client端:
server端:
client端向服務端注冊,服務端給客戶端發送響應的api_key以及security_key,注意保存不要泄露,然后客戶端根據api_key,secrity_key,timestrap,rest_uri采用hmacsha256算法得到一個hash值sign,構造途中的url發送給服務端。 服務端收到該請求后,首先驗證api_key,是否存在,存在則獲取該api_key的security_key,接著驗證timestrap是否超過時間限制,可依據系統成而定,這樣就防止了部分重放攻擊,途中的rest_api是從url獲取的為/rest/v1/interface/eth0,最后計算sign值,完之后和url中的sign值做校驗。這樣的設計就防止了數據被篡改。 通過這種API Key的設計方式加了時間戳防止了部分重放,加了校驗,防止了數據被篡改,同時避免了傳輸用戶名和密碼,當然了也會有一定的開銷。
OAuth2 協議適用于為外部應用授權訪問本站資源的情況。其中的加密機制與HTTP Digest身份認證相比,安全性更高。使用和配置都比較復雜,這里就不涉及了。
JWT 是JSON Web Token,用于發送可通過數字簽名和認證的東西,它包含一個緊湊的,URL安全的JSON對象,服務端可通過解析該值來驗證是否有操作權限,是否過期等安全性檢查。由于其緊湊的特點,可放在url中或者 HTTP Authorization頭中,具體的算法就如下圖
份認證之后就是授權,根據不同的身份,授予不同的訪問權限。比如admin用戶,普通用戶,auditor用戶都是不同的身份。簡單的示例:
$roles = array(
'ADMIN'=>array(
'permit'=>array('/^((\/system\/(clouds|device)$/'), // 允許訪問哪些URL的正則表達式
'deny'=>array('/^(\/system\/audit)$/') // 禁止訪問哪些URL的正則表達式
),
'AUDIT'=>array(
'permit'=>array('/^(\/system\/audit)$/'),//允許訪問的URL正則表達式
'deny'=>array('/^((\/system\/(clouds|device).*)$/')
)
);
上述是垂直權限的處理,如果遇到了平行權限的問題,如用戶A獲取用戶B的身份信息或者更改其他用戶信息,對于這些敏感數據接口都需要加上對用戶的判斷,這一步一般都在具體的邏輯實現中實現。
在進入邏輯處理之前,加入對URL的參數過濾,如
/site/{num}/policy
限定num位置為整數等,如果不是參數則直接返回非法參數,設定一個url清單,不在不在url清單中的請求直接拒絕,這樣能防止開發中的api泄露。
此處的設計原則與RESTful API設計原則中的URL命名規則一致。
優先使用SSSL確保鏈路安全。
報文內容二次加密,隱私性低的可以采用對稱秘鑰,隱私性高且防止抵賴需求采用證書模式的非對稱加密。
請求速率限制,根據api_key或者用戶來判斷某段時間的請求次數,將該數據更新到內存數據庫(redis,memcached),達到最大數即不接受該用戶的請求,同時這樣還可以利用到內存數據庫key在特定時間自動過期的特性。例如:在返回時設置X-Rate-Limit-Reset:當前時間段剩余秒數,APC的示例代碼如下:
Route::filter('api.limit', function()
{
$key = sprintf('api:%s', Auth::user()->api_key);
// Create the key if it doesn't exist
Cache::add($key, 0, 60);
// Increment by 1
$count = Cache::increment($key);
// Fail if hourly requests exceeded
if ($count > Config::get('api.requests_per_hour'))
{
App::abort(403, 'Hourly request limit exceeded');
}
});
對于非法的,導致系統出錯的等請求都進行記錄,一些重要的操作,如登錄,注冊等都通過日志接口輸出展示。有一個統一的出錯接口,對于400系列和500系列的錯誤都有相應的錯誤碼和相關消息提示,如401:未授權;403:已經鑒權,但是沒有相應權限。如不識別的url:
{"result":"Invalid URL!"}
錯誤的請求參數
{"result":"json format error"}
不允許的方法:
{"result":"Method Not Allowed"}
非法參數等。上面所說的都是單狀態碼,同時還有多狀態碼,表示部分成功,部分字符非法等。示例如下:
HTTP/1.1 207 Multi-Status
Content-Type: application/json; charset="UTF-8"
Content-Length: XXXX
{
"OPT_STATUS": 207
"DATA": {
"IP_ADDRESS": [{
"INTERFACE": "eth0",
"IP_LIST":[{
"IP": "192.168.1.1",
"MASK": "255.255.0.0",
"MULTI_STATUS": 200,
"MULTI_RESULT": "created successfully"
},{
"IP": "192.167.1.1",
"MASK": "255.255.0.0",
"MULTI_STATUS": 409,
"MULTI_RESULT": "invalid parameter"
}]
}]
},
隱私數據避免通過接口傳輸,如果必須傳遞,那么要做不透明處理,如果需要使用原始值,那么必須加密處理。
RESTful API設計概要
RESTful API 狀態碼設計指南
RESTful API 設計檢查清單
高質量的API文檔能夠提升API安全性
加強閱讀:19個API安全最佳實踐
RESTful API常見問題清單
轉載來源:https://www.kancloud.cn/kancloud/rest-api-design-safety