对于开发开放接口有很大的帮助,校验码存于header,密钥与内容关联二次加密,同时加上当前时间和随机字符串,安全性很高。
//头部
private static $header = array(
'alg' => 'HS256', //生成signature的算法
'typ' => 'JWT' //类型
);
public $app_id = '';
private $app_secret;
private $secretKey = '';
public function __construct($config)
{
$this->app_id = isset($config['appId']) ? $config['appId'] : '';
$this->app_secret = isset($config['appSecret']) ? $config['appSecret'] : '';
}
/**
* 获取jwt token
* @param array $payload jwt载荷 格式如下非必须
* [
* 'iss'=>'app885656565285656525656312', //该JWT的签发者
* 'iat'=>time(), //每一次请求都进行一次核验,此时间误差再3s范围以内
* 'exp'=>time()+3, //过期时间
* 'nbf'=>time()+10, //10s之后不再接收该token校验
* 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
* ]
* @return bool|string
*/
public function getToken()
{
$now = time();
$payload['iss'] = $this->app_id;
$payload['iat'] = $now;
$payload['exp'] = $now + 3;
$payload['nbf'] = $now + 10;
$payload['jti'] = md5(uniqid('JWT') . time());
$base64header = self::base64UrlEncode(json_encode(self::$header, JSON_UNESCAPED_UNICODE));
$base64payload = self::base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
$token = $base64header . '.' . $base64payload . '.' . self::signature($base64header . '.' . $base64payload, $this->secretKey, self::$header['alg']);
return $token;
}
/**
* HMACSHA256签名
* https://jwt.io/ 中HMACSHA256签名实现
* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
* @param string $key
* @param string $alg 算法方式
* @return mixed
*/
private static function signature($input, $key, $alg = 'HS256')
{
$alg_config = array(
'HS256' => 'sha256'
);
return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true));
}
/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现
* @param string $input 需要编码的字符串
* @return string
*/
private static function base64UrlEncode($input)
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
/**
* 对密钥进行二次加密
* @param $data
*/
public function signSecret($data)
{
$data['nonce_str'] = self::createNoncestr(32);
$data['timestamp'] = time();
$this->secretKey = self::getSignature($data, $this->app_secret);
return $data;
}
/**
* 数据生成签名
* @param array $data 签名数组
* @param string $method 签名方法
* @return bool|string 签名值
*/
public static function getSignature($data, $partnerKey, $method = "sha1")
{
if (!function_exists($method)) {
return false;
}
ksort($data);
$buff = '';
foreach ($data as $k => $v) {
$buff .= "{$k}={$v}&";
}
return $method(strtoupper(md5("{$buff}key={$partnerKey}")));
}
/**
* 产生随机字符串
* @param int $length 指定字符长度
* @param string $str 字符串前缀
* @return string
*/
public static function createNoncestr($length = 32, $str = "")
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/**
* 以post方式提交请求
* @param string $url
* @param array|string $data
* @return bool|mixed
*/
public static function httpPost($url, $data, $header = null)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
if ($header) {
curl_setopt($curl, CURLOPT_HTTPHEADER, self::_buildHeader($header));
// curl_setopt($curl, CURLOPT_HEADER, true);
} else {
curl_setopt($curl, CURLOPT_HEADER, false);
}
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
// $response = curl_exec($curl);
// $responseInfo = curl_getinfo($curl);
// curl_close($curl);
list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
return (intval($status["http_code"]) === 200) ? $content : false;
}
/**
* POST数据过滤处理
* @param array $data
* @return array
*/
static private function _buildHeader($data)
{
$newData = [];
if (is_array($data)) {
foreach ($data as $key => $value) {
$newData[] = $key . ":" . $value;
}
}
return $newData;
}
/**
* POST数据过滤处理
* @param array $data
* @return array
*/
static private function _buildPost(&$data)
{
if (is_array($data)) {
foreach ($data as &$value) {
if (is_string($value) && $value[0] === '@' && class_exists('CURLFile', false)) {
$filename = realpath(trim($value, '@'));
file_exists($filename) && $value = new CURLFile($filename);
}
}
}
return $data;
}
/**
* 使用证书,以post方式提交xml到对应的接口url
* @param string $url POST提交的内容
* @param array $data 请求的地址
* @param string $ssl_cer 证书Cer路径 | 证书内容
* @param string $ssl_key 证书Key路径 | 证书内容
* @param int $second 设置请求超时时间
* @return bool|mixed
*/
static public function httpsPost($url, $data, $header = null, $ssl_cer = null, $ssl_key = null, $second = 30)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_TIMEOUT, $second);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
if ($header) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
}
if (!is_null($ssl_cer) && file_exists($ssl_cer) && is_file($ssl_cer)) {
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLCERT, $ssl_cer);
}
if (!is_null($ssl_key) && file_exists($ssl_key) && is_file($ssl_key)) {
curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLKEY, $ssl_key);
}
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
return (intval($status["http_code"]) === 200) ? $content : false;
}
|