介面簽名
介面簽名是一種常見的安全措施,用於確保API請求的完整性和身份驗證。
實作步驟
以下是實作介面簽名的一般步驟:
參數收集 :首先,收集所有將發送到API的參數,包括例如使用者ID、操作型別、請求數據等。
排序 :為了確保簽名的一致性,通常需要對參數進行字典序排序。
拼接字串 :將排序後的參數與其值拼接成一個字串。通常還會在這個字串中包含一個時間戳和一個金鑰(Secret Key)。例如:
stringToSign = method + path + params + timestamp + secretKey
其中:
method
是HTTP請求方法,如GET或POST。
path
是API的路徑。
params
是經過排序的參數字串。
timestamp
是請求發起的時間戳。
secretKey
是只有伺服器和客戶端知道的金鑰。
雜湊加密
:使用一個雜湊函式,如MD5、SHA-1或SHA-256,對上一步生成的字串進行加密,生成簽名。例如:
sign = hash(stringToSign)
發送請求
:在發送API請求時,在請求參數或請求頭中增加
sign
參數。
伺服器驗證 :伺服器接收到請求後,會用相同的方法重新生成簽名,並與客戶端提供的簽名進行比對。如果兩者一致,則認為請求是合法的。
安全考慮 :
確保
secretKey
安全,不要泄露給未經授權的第三方。
可以考慮使用HTTPS來加密傳輸過程,防止中間人攻擊。
簽名中包含時間戳可以防止重放攻擊,需要驗證時間戳的有效性。
錯誤處理 :如果簽名驗證失敗,伺服器應該返回一個錯誤響應,並記錄可能的安全事件。介面簽名機制能夠有效地防止API請求被篡改,確保數據的安全性和請求的合法性。不過,它不提供加密通訊的功能,因此對於敏感資訊的傳輸,還需要結合使用加密技術。
案例
生成金鑰對
$originalUuid = Uuid::uuid4()->toString();
$app_key = str_replace('-', '', $originalUuid); // 唯一標識ID uuid
$timestamp = time();
$app_secret = sha1($app_key . '|'.$timestamp); // sha1(app_key + update_time)
$createData = [
'app_name' => '阿克蘇平台',
'app_key' => $app_key,
'app_secret' => password_hash($app_secret, PASSWORD_DEFAULT), // 加密保存
'create_time' => $timestamp,
'update_time' => $timestamp
];
if(AppModel::create($createData)){
return response_json(200, 'ok');
}
校驗簽名
// [1] 從請求頭中獲取簽名
$signature = $this->request->header()['x-resty-signature'] ?? '';
// [2] 簽名解析 獲取: 哈希演算法 和 明文數據
list($hashType, $hashValue) = explode('=', $signature, 2);
// [3] 獲取請求的內容,格式為json字元換
$jsonContent = $this->request->getContent();
if(empty($jsonContent)) {
return response_json(400, '請求內容不能為空');
}
$arrayContent = json_decode($jsonContent, true);
if(!isset($arrayContent['app_key']) || !isset($arrayContent['timestamp'])) {
return response_json(400, '請求app_key timestamp不能為空');
}
if (($arrayContent['timestamp'] + 20) < time() ) {
return response_json(403, 'timestamp過期');
}
$appInfo = AppModel::where('app_key',$arrayContent['app_key'])->findOrEmpty();
if($appInfo->isEmpty()) {
return response_json(400, '無效的app_key');
}
// [4] 生成 appSecret
$appSecret = sha1($appInfo->app_key . '|'.$appInfo->update_time);
// [5] hash_hmac — 使用 HMAC 方法生成帶有金鑰的哈希值
$checkHash = hash_hmac($hashType, json_encode($arrayContent), $appSecret);
// [6] 簽名校驗
if ($checkHash != $hashValue) {
return response_json(403, '無效的簽名',$this->request->header());
}
return response_json(200, 'ok',$arrayContent);
數據加密
在設計和實作API介面時,我們經常需要處理一些敏感數據,例如使用者的登入密碼、銀行卡號、身份證號碼等。這些資訊若以明文形式在網路上傳輸,將面臨極大的安全風險,容易受到惡意監聽和數據泄露的威脅。
在設計和實作API介面時,我們經常需要處理一些敏感數據,例如使用者的登入密碼、銀行卡號、轉賬金額和身份證號碼等。這些資訊若以明文形式在網路上傳輸,將面臨極大的安全風險,容易受到惡意監聽和數據泄露的威脅。
安全建議
為了確保這些關鍵資訊的安全,我們必須采取加密措施來保護數據的完整性和私密性。以下是一些加強數據安全的建議:
使用HTTPS :始終透過HTTPS協定發送數據,利用SSL/TLS加密層來保護數據傳輸過程中的安全。
敏感數據加密 :對於特別敏感的資訊,如登入密碼,應在客戶端側進行加密處理,確保只有授權的伺服器端能夠解密並存取原始數據。
雜湊密碼儲存 :對於密碼等驗證資訊,不應以明文形式儲存或傳輸。應使用強雜湊函式(如bcrypt、scrypt或Argon2)來處理密碼,並儲存雜湊值。
案例
SM4演算法是一種分組密碼演算法。其分組長度為128bit,金鑰長度也為128bit。加密演算法與金鑰擴充套件演算法均采用32輪非線性叠代結構,以字(32位元)為單位進行加密運算,每一次叠代運算均為一輪變換函式F。SM4演算法加/解密演算法的結構相同,只是使用輪金鑰相反,其中解密輪金鑰是加密輪金鑰的逆序。
SM4加密方式類似於AES加密,為對稱加密,可以透過相應的秘鑰進行加密和解密
加密
$key = '35d251411ea04318565f0dbda6ffb6a8';
// 加密內容
$content = [
'name' => 'Tinywan',
'School' => 'ZheJiang University',
'age' => 24,
'github' => [
'url' => 'https://github.com/Tinywan',
'start' => 2000,
],
];
// 必須轉換為字串
$content = json_encode($content, JSON_UNESCAPED_UNICODE);
$sm4 = new SM4($key);
$encryptContent = $sm4->encrypt($content);
var_dump($encryptContent);
// 加密內容:b4358f5860343dbf2089ba75ee55deca8d922a069413f39cb3f8b64c01048c780ba5f03290642505d65d79c59684d76cf42443047f547c9f29dc2a49f872a2719ce00539058ab1fb5830e8e0c10144b574a87118390baa765b3429ba7afe5d28
解密
$key = '35d251411ea04318565f0dbda6ffb6a8';
// 加密內容
$encryptContent = 'b4358f5860343dbf2089ba75ee55deca8d922a069413f39cb3f8b64c01048c780ba5f03290642505d65d79c59684d76cf42443047f547c9f29dc2a49f872a2719ce00539058ab1fb5830e8e0c10144b574a87118390baa765b3429ba7afe5d28';
$sm4 = new SM4($key);
$decryptedJsonContent = $sm4->decrypt($encryptContent);
print_r($decryptedJsonContent);
解密結果
{
"name": "Tinywan",
"School": "ZheJiang University",
"age": 24,
"github": {
"url": "https://github.com/Tinywan",
"start": 2021
}
}
可以透過 json_decode($decryptedJsonContent, true) ,轉換為陣列使用
響應格式統一
API介面響應格式的統一對於客戶端開發者來說非常重要,它有助於提高開發效率、降低出錯率,並能夠快速整合和偵錯介面。
格式建議
以下是一些建議,用於確保API響應格式的統一性:
明確的版本號 :在響應中包含API版本號,這樣在API更新時可以保持回溯相容性。
統一的狀態碼 :使用標準HTTP狀態碼來表示請求的結果,如200表示成功,400表示客戶端錯誤,500表示伺服器錯誤等。
數據封裝 :響應的數據應該被封裝在一個統一的欄位中,例如
data
,這樣可以在不同的響應中保持一致性。分頁資訊 :如果響應數據支持分頁,應提供統一的分頁資訊,如
total
(總記錄數)、perPage
(每頁記錄數)、currentPage
(當前頁碼)和totalPages
(總頁數)。
透過以上措施,可以確保API介面的響應格式統一、清晰,並且易於客戶端開發者使用和整合。
案例
成功範例
HTTP/1.1200 OK
Content-Type: application/json;charset=UTF-8
{
"code": 0,
"msg": "success",
"data": {
"token_type": "Bearer",
"expires_in": 7200,
"access_token": "XXXXXXXXXXX"
}
}
異常例項
HTTP/1.1401 Unauthorized
Content-Type: application/json;charset=UTF-8
{
"code": 0,
"msg": "套用資訊不存在",
"data": {}
}