api接口签名加密请求(二)
阅读(1513)
2018-01-12
在“api接口签名加密请求,从springmvc4项目搭建开始”篇文章,讲述了使用java springmvc搭建api接口请求例子。为了方便php能调用,接着写了php的demo例子。
回顾上回
api接口设计方式和思路
1、公开性
接口是公网可访问的,不希望被随便请求,需要token签名认证才能调用,接口提供方提供接口密钥。
2、安全性
模拟支付宝接口签名方式签名,请求参数按照key=value&key=value方式拼接的未签名原始字符串(含时间戳),再对原始字符串进行签名(加密钥)。如:md5(id=1×tamp=1514020967 + 密钥)
3、模式性
请求
请求参数 + 时间戳 + 签名(请求参数+时间戳+密钥)
接收
md5(接收参数(去除签名) + 密钥) == 接收参数(签名)
后再比较 接收参数(时间戳) 跟 当前系统时间戳 的时效性
签名请求函数
/** 密钥 */ define("KEY","weizhixi"); /** 模拟post */ function curl_post($url, $params){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type:application/x-www-form-urlencoded; charset=utf-8']); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($curl, CURLOPT_POSTFIELDS, $params); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($curl); if($data === false) echo 'Curl error: ' . curl_error($curl); curl_close($curl); return $data; } /** 模拟get */ function curl_get($url, $params){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url.'?'.$params); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type:application/x-www-form-urlencoded; charset=utf-8']); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); $data = curl_exec($curl); if($data === false) echo 'Curl error: ' . curl_error($curl); curl_close($curl); return $data; } /** * 生成签名 * 除去数组中的空值和签名参数 * 对数组排序,把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 * @param $params 需要签名的数组 * @return md5签名 */ function buildSign($params) { //去数组中的空值和签名 $para = array(); while (list ($key, $val) = each ($params)){ if($key == "sign" || $val === "" || $val === null){ continue; }else{ $para[$key] = $params[$key]; } } //对数组排序 ksort($para); reset($para); //生成,参数=参数值 $arg = ""; while (list ($key, $val) = each ($para)){ if(is_array($val)){ $val = implode(",",$val); } $arg .= $key."=".$val."&"; } //去掉最后一个&字符 $arg = substr($arg,0,count($arg)-2); //如果存在转义字符,那么去掉转义 if(get_magic_quotes_gpc()) $arg = stripslashes($arg); //签名 return md5($arg . KEY); } /** * 验证签名 * @param $params 返回来的参数数组 * @return 签名验证结果 */ function verifySign($params) { //返回的签名结果 $sign = $params['sign']; $timestamp = $params['timestamp']; //我的签名 $mySgin = buildSign($params); if ($mySgin == $sign) { //时间不能为空 if(empty($timestamp)) return false; var_dump(time() ."-". $timestamp); //是否超时 if((time() - $timestamp) > 15) return false; return true; } else { return false; } } /** * 生成要请求的参数数组 * @param $params 请求前的参数数组 * @return 要请求的参数字符串 */ function signString($params) { //生成签名 $params['timestamp'] = time(); $params['sign'] = buildSign($params); return createLinkStringUrlEncode($params); } /** * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码 * @param $para 需要拼接的数组 * @return string 拼接完成以后的字符串 */ function createLinkStringUrlEncode($para) { $arg = ""; while (list ($key, $val) = each ($para)) { if(is_array($val)){ while (list ($k, $v) = each ($val)) { //$arg.=$key."[]=".urlencode($v)."&"; $arg.=$key."=".urlencode($v)."&"; } }else{ $arg.=$key."=".urlencode($val)."&"; } } //去掉最后一个&字符 $arg = substr($arg,0,count($arg)-2); //如果存在转义字符,那么去掉转义 if(get_magic_quotes_gpc()){$arg = stripslashes($arg);} return $arg; }
使用示例:
调用api请求:
$url = "http://localhost:8080/api/v1/index/save"; $params = array( "id" => "1", "name" => "微知兮", "tags" => array("1","2","3") ); $params = signString($params); $result = curl_post($url, $params); print_r(json_decode($result, true));
验证请求:
if(verifySign($_POST)){ echo '验证成功'; }else{ echo '验证失败'; }
至此,api已经介绍完毕,已附上java完整例子和php版例子,如需要请自行下载,如需要可看回java的版本文章。
本例子仅供学习研究,由于写的比较仓促,如有不妥当的地方欢迎指出。
已下载:526 次
已下载:840 次
原创文章,转载请注明出处:https://www.weizhixi.com/article/58.html