簽名功能在api開發(fā)中用于驗證請求合法性,防止數(shù)據(jù)篡改。其核心在于生成和驗證簽名字符串的一致性。1. 簽名原理是對參數(shù)排序拼接后用密鑰加密,常用md5或hmac-sha256;2. php實現(xiàn)需過濾sign字段、排序參數(shù)、拼接字符串、附加密鑰并加密;3. 服務(wù)端驗證流程為復(fù)現(xiàn)簽名生成過程并與客戶端簽名對比;4. 實際開發(fā)建議包括時間戳校驗、使用nonce防重放、啟用https、簽名字段不參與拼接、統(tǒng)一編碼格式等。
簽名功能在API開發(fā)中很常見,主要用于驗證請求的合法性,防止數(shù)據(jù)被篡改。PHP實現(xiàn)簽名的方式其實不復(fù)雜,核心在于生成和驗證簽名字符串的一致性。
一、簽名的基本原理
簽名的本質(zhì)是:對請求參數(shù)進行排序、拼接,并使用密鑰進行加密,生成一段唯一字符串作為簽名值。服務(wù)端收到請求后,按照同樣的規(guī)則重新計算簽名,與傳入的簽名對比,一致則認為合法。
常見做法是使用 MD5 或 HMAC-SHA256 等算法進行加密。
立即學(xué)習(xí)“PHP免費學(xué)習(xí)筆記(深入)”;
舉個例子:
- 客戶端傳參:username=admin×tamp=1717029200
- 拼接成:admin_1717029200
- 加密成簽名:md5(admin_1717029200_secret_key) → 得到一個32位字符串
- 請求帶上該簽名,服務(wù)端做同樣處理并比對
二、PHP生成簽名的方法
以下是一個簡單的PHP簽名生成示例:
function generateSign($params, $secretKey) { // 1. 過濾掉sign字段 unset($params['sign']); // 2. 參數(shù)按key排序 ksort($params); // 3. 拼接 key=value 形式 $str = ''; foreach ($params as $k => $v) { if ($v !== '') { // 可選:過濾空值 $str .= $k . '=' . $v . '&'; } } // 4. 去掉末尾的& $str = rtrim($str, '&'); // 5. 拼接密鑰 $str .= $secretKey; // 6. 使用MD5或sha256等算法生成簽名 return md5($str); }
調(diào)用方式:
$params = [ 'username' => 'admin', 'timestamp' => time(), ]; $secretKey = 'your_secret_key'; $sign = generateSign($params, $secretKey);
三、服務(wù)端如何驗證簽名
服務(wù)端的驗證流程基本就是客戶端生成簽名的復(fù)現(xiàn)過程:
- 接收所有請求參數(shù)(GET/POST)
- 提取簽名字段(如 sign)
- 按照相同規(guī)則生成簽名
- 對比是否一致
關(guān)鍵點:
- 時間戳的有效期控制(比如允許前后5分鐘內(nèi))
- 密鑰不能泄露
- 避免重復(fù)請求(可記錄已使用的nonce)
驗證代碼大致如下:
function verifySign($params, $secretKey) { $clientSign = $params['sign'] ?? ''; if (!$clientSign) return false; $serverSign = generateSign($params, $secretKey); return $clientSign === $serverSign; }
四、一些實際開發(fā)中的建議
- 時間戳校驗:一般會要求客戶端傳遞時間戳,并限制最大誤差范圍(比如5分鐘),防止重放攻擊。
- 使用nonce防重放:每次請求帶一個唯一隨機串,服務(wù)端緩存一段時間,避免同一請求多次生效。
- HTTPS傳輸更安全:即使簽名再強,明文傳輸也有風險,務(wù)必啟用HTTPS。
- 簽名字段不要參與拼接:否則會導(dǎo)致死循環(huán)。
- 統(tǒng)一編碼格式:URL編碼、大小寫敏感這些細節(jié)要統(tǒng)一處理。
基本上就這些。簽名機制看似簡單,但如果不注意細節(jié),很容易留下漏洞。只要邏輯清晰、規(guī)則統(tǒng)一,就能在大多數(shù)項目中穩(wěn)定使用。