當前位置: 妍妍網 > 碼農

標準API介面設計規範

2024-06-01碼農

介面簽名

介面簽名是一種常見的安全措施,用於確保API請求的完整性和身份驗證。

實作步驟

以下是實作介面簽名的一般步驟:

  1. 參數收集 :首先,收集所有將發送到API的參數,包括例如使用者ID、操作型別、請求數據等。

  2. 排序 :為了確保簽名的一致性,通常需要對參數進行字典序排序。

  3. 拼接字串 :將排序後的參數與其值拼接成一個字串。通常還會在這個字串中包含一個時間戳和一個金鑰(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($jsonContenttrue);
    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介面時,我們經常需要處理一些敏感數據,例如使用者的登入密碼、銀行卡號、轉賬金額和身份證號碼等。這些資訊若以明文形式在網路上傳輸,將面臨極大的安全風險,容易受到惡意監聽和數據泄露的威脅。

    安全建議

    為了確保這些關鍵資訊的安全,我們必須采取加密措施來保護數據的完整性和私密性。以下是一些加強數據安全的建議:

    1. 使用HTTPS :始終透過HTTPS協定發送數據,利用SSL/TLS加密層來保護數據傳輸過程中的安全。

    2. 敏感數據加密 :對於特別敏感的資訊,如登入密碼,應在客戶端側進行加密處理,確保只有授權的伺服器端能夠解密並存取原始數據。

    3. 雜湊密碼儲存 :對於密碼等驗證資訊,不應以明文形式儲存或傳輸。應使用強雜湊函式(如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響應格式的統一性:

    1. 明確的版本號 :在響應中包含API版本號,這樣在API更新時可以保持回溯相容性。

    2. 統一的狀態碼 :使用標準HTTP狀態碼來表示請求的結果,如200表示成功,400表示客戶端錯誤,500表示伺服器錯誤等。

    3. 數據封裝 :響應的數據應該被封裝在一個統一的欄位中,例如 data ,這樣可以在不同的響應中保持一致性。

    4. 分頁資訊 :如果響應數據支持分頁,應提供統一的分頁資訊,如 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": {}
    }