123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- <?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']; // 只获取参与签名的头部字段
- $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 (self::$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[$k] = $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);
- }
- }
- ?>
|