接口簽名生成+驗(yàn)證
在做一些api接口設(shè)計(jì)時(shí)候會(huì)遇到設(shè)置權(quán)限問(wèn)題,比如我這個(gè)接口只有指定的用戶才能訪問(wèn)。
很多時(shí)候api接口是屬于無(wú)狀態(tài)的,沒(méi)辦法獲取session,就不能夠用登錄的機(jī)制去驗(yàn)證,那么
大概的思路是在請(qǐng)求包帶上我們自己構(gòu)造好的簽名,這個(gè)簽名必須滿足下面幾點(diǎn):
- 唯一性,簽名是唯一的,可驗(yàn)證目標(biāo)用戶
- 可變性,每次攜帶的簽名必須是變化的
- 時(shí)效性,具有一定的時(shí)效,過(guò)期作廢
- 完整性,能夠?qū)?shù)據(jù)包進(jìn)行驗(yàn)證,防止篡改
<?php
// 設(shè)置一個(gè)公鑰(key)和私鑰(secret),公鑰用于區(qū)分用戶,私鑰加密數(shù)據(jù),不能公開(kāi) $key = "c4ca4238a0b923820dcc509a6f75849b"; $secret = "28c8edde3d61a0411511d3b1866f0636"; // 待發(fā)送的數(shù)據(jù)包 $data = array( 'username' => 'abc@qq.com', 'sex' => '1', 'age' => '16', 'addr' => 'guangzhou', 'key' => $key, 'timestamp' => time(), ); // 獲取sign function getSign($secret, $data) { // 對(duì)數(shù)組的值按key排序 ksort($data); // 生成url的形式 $params = http_build_query($data); // 生成sign $sign = md5($params . $secret); return $sign; } // 發(fā)送的數(shù)據(jù)加上sign $data['sign'] = getSign($secret, $data); /** * 后臺(tái)驗(yàn)證sign是否合法 * @param [type] $secret [description] * @param [type] $data [description] * @return [type] [description] */ function verifySign($secret, $data) { // 驗(yàn)證參數(shù)中是否有簽名 if (!isset($data['sign']) || !$data['sign']) { echo '發(fā)送的數(shù)據(jù)簽名不存在'; die(); } if (!isset($data['timestamp']) || !$data['timestamp']) { echo '發(fā)送的數(shù)據(jù)參數(shù)不合法'; die(); } // 驗(yàn)證請(qǐng)求, 10分鐘失效 if (time() - $data['timestamp'] > 600) { echo '驗(yàn)證失效, 請(qǐng)重新發(fā)送請(qǐng)求'; die(); } $sign = $data['sign']; unset($data['sign']); ksort($data); $params = http_build_query($data); // $secret是通過(guò)key在api的數(shù)據(jù)庫(kù)中查詢得到 $sign2 = md5($params . $secret); if ($sign == $sign2) { die('驗(yàn)證通過(guò)'); } else { die('請(qǐng)求不合法'); } }

浙公網(wǎng)安備 33010602011771號(hào)