123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- <?php
- class SpiUtils{
- private static $top_sign_list = "HTTP_TOP_SIGN_LIST";
- private static $timestamp = "timestamp";
- private static $header_real_ip = array("X_Real_IP", "X_Forwarded_For", "Proxy_Client_IP",
- "WL_Proxy_Client_IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");
- /**
- * 校验SPI请求签名,适用于所有GET请求,及不包含文件参数的POST请求。
- *
- * @param request 请求对象
- * @param secret app对应的secret
- * @return true:校验通过;false:校验不通过
- */
- public static function checkSign4FormRequest($secret){
- return self::checkSign(null,null,$secret);
- }
- /**
- * 校验SPI请求签名,适用于请求体是xml/json等可用文本表示的POST请求。
- *
- * @param request 请求对象
- * @param body 请求体的文本内容
- * @param secret app对应的secret
- * @return true:校验通过;false:校验不通过
- */
- public static function checkSign4TextRequest($body,$secret){
- return self::checkSign(null,$body,$secret);
- }
-
- /**
- * 校验SPI请求签名,适用于带文件上传的POST请求。
- *
- * @param request 请求对象
- * @param form 除了文件参数以外的所有普通文本参数的map集合
- * @param secret app对应的secret
- * @return true:校验通过;false:校验不通过
- */
- public static function checkSign4FileRequest($form, $secret){
- return self::checkSign($form, null, $secret);
- }
- private static function checkSign($form, $body, $secret) {
- $params = array();
- // 1. 获取header参数
- $headerMap = self::getHeaderMap();
- foreach ($headerMap as $k => $v){
- $params[$k] = $v ;
- }
- // 2. 获取url参数
- $queryMap = self::getQueryMap();
- foreach ($queryMap as $k => $v){
- $params[$k] = $v ;
- }
- // 3. 获取form参数
- if ($form == null && $body == null) {
- $formMap = self::getFormMap();
- foreach ($formMap as $k => $v){
- $params[$k] = $v ;
- }
- } else if ($form != null) {
- foreach ($form as $k => $v){
- $params[$k] = $v ;
- }
- }
- if($body == null){
- $body = file_get_contents('php://input');
- }
- $remoteSign = $queryMap["sign"];
- $localSign = self::sign($params, $body, $secret);
- if (strcmp($remoteSign, $localSign) == 0) {
- return true;
- } else {
- $paramStr = self::getParamStrFromMap($params);
- self::logCommunicationError($remoteSign,$localSign,$paramStr,$body);
- return false;
- }
- }
- private static function getHeaderMap() {
- $headerMap = array();
- $signList = $_SERVER['HTTP_TOP_SIGN_LIST']; // 只获取参与签名的头部字段
- if(!$signList) {
- return $headerMap;
- }
- $signList = trim($signList);
- if (strlen($signList) > 0){
- $params = split(",", $signList);
- foreach ($_SERVER as $k => $v){
- if (substr($k, 0, 5) == 'HTTP_'){
- foreach($params as $kk){
- $upperkey = strtoupper($kk);
- if(self::endWith($k,$upperkey)){
- $headerMap[$kk] = $v;
- }
- }
- }
- }
- }
- return $headerMap;
- }
- private static function getQueryMap(){
- $queryStr = $_SERVER["QUERY_STRING"];
- $resultArray = array();
- foreach (explode('&', $queryStr) as $pair) {
- list($key, $value) = explode('=', $pair);
- if (strpos($key, '.') !== false) {
- list($subKey, $subVal) = explode('.', $key);
- if (preg_match('/(?P<name>\w+)\[(?P<index>\w+)\]/', $subKey, $matches)) {
- $resultArray[$matches['name']][$matches['index']][$subVal] = $value;
- } else {
- $resultArray[$subKey][$subVal] = urldecode($value);
- }
- } else {
- $resultArray[$key] = urldecode($value);
- }
- }
- return $resultArray;
- }
- private static function checkRemoteIp(){
- $remoteIp = $_SERVER["REMOTE_ADDR"];
- foreach ($header_real_ip as $k){
- $realIp = $_SERVER[$k];
- $realIp = trim($realIp);
- if(strlen($realIp) > 0 && strcasecmp("unknown",$realIp)){
- $remoteIp = $realIp;
- break;
- }
- }
- return self::startsWith($remoteIp,"140.205.144.") || self::startsWith($remoteIp,"40.205.145.");
- }
- private static function getFormMap(){
- $resultArray = array();
- foreach($_POST as $key=>$v) {
- $resultArray[$key] = $v ;
- }
- return $resultArray ;
- }
- private static function startsWith($haystack, $needle) {
- return $needle === "" || strpos($haystack, $needle) === 0;
- }
- private static function endWith($haystack, $needle) {
- $length = strlen($needle);
- if($length == 0)
- {
- return true;
- }
- return (substr($haystack, -$length) === $needle);
- }
- private static function checkTimestamp(){
- $ts = $_POST['timestamp'];
- if($ts){
- $clientTimestamp = strtotime($ts);
- $current = $_SERVER['REQUEST_TIME'];
- return ($current - $clientTimestamp) <= 5*60*1000;
- }else{
- return false;
- }
- }
- private static function getParamStrFromMap($params){
- ksort($params);
- $stringToBeSigned = "";
- foreach ($params as $k => $v)
- {
- if(strcmp("sign", $k) != 0)
- {
- $stringToBeSigned .= "$k$v";
- }
- }
- unset($k, $v);
- return $stringToBeSigned;
- }
- private static function sign($params,$body,$secret){
- ksort($params);
- $stringToBeSigned = $secret;
- $stringToBeSigned .= self::getParamStrFromMap($params);
- if($body)
- $stringToBeSigned .= $body;
- $stringToBeSigned .= $secret;
- return strtoupper(md5($stringToBeSigned));
- }
- protected static function logCommunicationError($remoteSign, $localSign, $paramStr, $body)
- {
- $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
- $logger = new TopLogger;
- $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_". date("Y-m-d") . ".log";
- $logger->conf["separator"] = "^_^";
- $logData = array(
- "checkTopSign error" ,
- "remoteSign=".$remoteSign ,
- "localSign=".$localSign ,
- "paramStr=".$paramStr ,
- "body=".$body
- );
- $logger->log($logData);
- }
- private static function clear_blank($str, $glue='')
- {
- $replace = array(" ", "\r", "\n", "\t"); return str_replace($replace, $glue, $str);
- }
- }
- ?>
|