標籤:value 開啟 family request http請求 lower 路徑 make 客戶
就安全來說,所有用戶端和伺服器端的通訊內容應該都要通過加密通道(HTTPS)傳輸,明文的HTTP通道將會是man-in-the- middle及其各種變種攻擊的溫床。所謂man-in-the-middle攻擊簡單講就是指惡意的駭客可以在用戶端和伺服器端的明文通訊通道上做手 腳,駭客可以監聽通訊內容,偷取機密資訊,甚至可以篡改通訊內容,而通過加密後的通訊內容理論上是無法被破譯的。
URL簽名建置規則
API的有效訪問URL包括以下三個部分: 1. 資源訪問路徑,如/v1/deal/find_deals; 2. 請求參數:即API對應所需的參數名和參數值param=value,多個請求參數間用&串連如deal_id=1-85462&appid=00000; 3. 簽名串,由簽名演算法產生 |
簽名演算法如下:
1. 對所有請求參數進行字典升序排列; 2. 將以上排序後的參數表進行字串串連,如key1value1key2value2key3value3...keyNvalueN; 3. app secret作為尾碼,對該字串進行SHA-1計算,並轉換成16進位編碼; 4. 轉換為全大寫形式後即獲得簽名串 |
注意:請保證HTTP請求資料編碼務必為UTF-8格式,URL也務必為UTF-8編碼格式。
舉個執行個體:
PHP服務端先要給開發人員(APP)分配一個appid與appsecret (正常情況下,開發人員要到服務提供者的官網申請),作為用戶端,需要保留好官方頒發的appid & appsecret
appid會在請求中作為一個應用標識參與介面請求的參數傳遞,appsecret 將作為唯一不需要參數傳遞,但是它將作為驗證當前請求的關鍵參數,只有應用開發人員和頒發的服務端才知道。由於簽名是依靠同樣的演算法加密實現,因此,應用端和服務端可以計算出相同的簽名值,簽名實際意義在於服務端對用戶端的訪問身份認證。在某種意義上籤名機制有點類似用公開金鑰方法簽名,用每個應用對應的私密金鑰值來解密,只是這種解密過程實質就是核對簽名參數值的過程。
假設分配:
$appid=5288971;$appsecret= ‘r5e2t85tyu142u665698fzu‘;
移動用戶端,需要請求服務列表(以下代碼可以為java或sf等移動端編寫)
請求地址: http://web.com/server/list
參數:
$array=[‘appid‘=>5288971,‘menu‘=>‘客戶服務列表‘,‘lat‘=>21.223,‘lng‘=>131.334 ];
對應簽名演算法
// 1. 對加密數組進行字典排序foreach ($array as $key=>$value){ $arr[$key] = $key; } sort($arr); //字典排序的作用就是防止因為參數順序不一致而導致下面拼接加密不同 // 2. 將Key和Value拼接 $str = "";foreach ($arr as $k => $v) { $str = $str.$arr[$k].$array[$v];}//3. 通過sha1加密並轉化為大寫//4. 大寫獲得簽名$restr=$str.$appsecret;$sign = strtoupper(sha1($restr));
將生產的sign簽名一起寫入array中,通過約定好的method方式發送參數到請求介面
$array[‘sign‘]=$sign;
列印$array
Array( [appid] => 5288971 [menu] => 客戶服務列表 [lat] => 21.223 [lng] => 131.334 [sign] => C096D7811E944386CE880597BA334A5AB640B088)
用戶端將資料封裝xml或Json發送到服務端,服務端先解析
{"appid":5288971,"menu":"\u5ba2\u6237\u670d\u52a1\u5217\u8868","lat":21.223,"lng":131.334,"sign":"C096D7811E944386CE880597BA334A5AB640B088"}
$serverArray= json_decode($json,TRUE);
服務端查詢appid對應的密鑰
$model=Model::find()->where("appid=:appid")->params([":appid"=>$serverArray[‘appid‘]])->one(); if($model){ $serverSecret=$model->appsecret;}
按照相同的字典排序與演算法產生服務端的$sign ,判斷$sign 是否相同。
$clientSign=$array[‘sign‘];unset($serverArray[‘sign‘]);#產生服務端str$serverstr = "";foreach ($serverArray as $k => $v) { $serverstr = $str.$k.$v;}$reserverstr=$str.$serverSecret;$reserverSign = strtoupper(sha1($reserverstr));if($clientSign!=$reserverSign){ die(‘非法請求‘);}else{// your code continue;}
在僅適用簡訊登入做手機端app時,可以設定secret的到期時間,簡訊登入後,儲存appid(userid)與密鑰secret,每當使用者開啟APP時,先連網請求登入是否到期,到期重新簡訊登入擷取新的secret。
附加:
有時,我們使用hash_hmac進行加密(我們項目中使用……)
/* * 產生簽名,$args為請求參數,$key為私密金鑰 */function makeSignature($args, $key){ if(isset($args[‘sign‘])) { $oldSign = $args[‘sign‘]; unset($args[‘sign‘]); } else { $oldSign = ‘‘; } ksort($args); $requestString = ‘‘; foreach($args as $k => $v) { $requestString .= $k . ‘=‘ . urlencode($v); } $newSign = hash_hmac("md5",strtolower($requestString) , $key); return $newSign;}
PHP 開發API介面簽名驗證