175 lines
5.2 KiB
PHP
175 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace app\common\service;
|
|
|
|
/**
|
|
* 腾讯云IM UserSig生成类(官方算法)
|
|
* 参考:https://github.com/tencentyun/tls-sig-api-v2-php
|
|
*/
|
|
class TLSSigAPIv2
|
|
{
|
|
private $sdkappid;
|
|
private $key;
|
|
|
|
public function __construct($sdkappid, $key)
|
|
{
|
|
$this->sdkappid = $sdkappid;
|
|
$this->key = $key;
|
|
}
|
|
|
|
/**
|
|
* 生成UserSig
|
|
* @param string $identifier 用户ID
|
|
* @param int $expire 过期时间(秒)
|
|
* @return string UserSig
|
|
*/
|
|
public function genUserSig($identifier, $expire = 86400)
|
|
{
|
|
return $this->__genSig($identifier, $expire, '', false);
|
|
}
|
|
|
|
/**
|
|
* 生成带权限的UserSig
|
|
* @param string $identifier 用户ID
|
|
* @param int $expire 过期时间(秒)
|
|
* @param string $userbuf 用户权限buffer
|
|
* @return string UserSig
|
|
*/
|
|
public function genUserSigWithUserBuf($identifier, $expire, $userbuf)
|
|
{
|
|
return $this->__genSig($identifier, $expire, $userbuf, true);
|
|
}
|
|
|
|
/**
|
|
* 内部方法:生成签名
|
|
*/
|
|
private function __genSig($identifier, $expire, $userbuf, $userbuf_enabled)
|
|
{
|
|
$current = time();
|
|
$sigDoc = [
|
|
'TLS.ver' => '2.0',
|
|
'TLS.identifier' => strval($identifier),
|
|
'TLS.sdkappid' => intval($this->sdkappid),
|
|
'TLS.expire' => intval($expire),
|
|
'TLS.time' => intval($current)
|
|
];
|
|
|
|
$base64_userbuf = '';
|
|
if ($userbuf_enabled) {
|
|
$base64_userbuf = base64_encode($userbuf);
|
|
$sigDoc['TLS.userbuf'] = $base64_userbuf;
|
|
}
|
|
|
|
$sig = $this->hmacsha256($identifier, $current, $expire, $base64_userbuf, $userbuf_enabled);
|
|
$sigDoc['TLS.sig'] = base64_encode($sig);
|
|
|
|
$json_text = json_encode($sigDoc);
|
|
$compressed = gzcompress($json_text);
|
|
|
|
return $this->base64_url_encode($compressed);
|
|
}
|
|
|
|
/**
|
|
* 生成HMAC-SHA256签名
|
|
*/
|
|
private function hmacsha256($identifier, $curr_time, $expire, $base64_userbuf, $userbuf_enabled)
|
|
{
|
|
$content_to_be_signed = "TLS.identifier:" . $identifier . "\n"
|
|
. "TLS.sdkappid:" . $this->sdkappid . "\n"
|
|
. "TLS.time:" . $curr_time . "\n"
|
|
. "TLS.expire:" . $expire . "\n";
|
|
|
|
if ($userbuf_enabled) {
|
|
$content_to_be_signed .= "TLS.userbuf:" . $base64_userbuf . "\n";
|
|
}
|
|
|
|
return hash_hmac('sha256', $content_to_be_signed, $this->key, true);
|
|
}
|
|
|
|
/**
|
|
* Base64 URL安全编码
|
|
*/
|
|
private function base64_url_encode($input)
|
|
{
|
|
return str_replace(['+', '/', '='], ['*', '-', '_'], base64_encode($input));
|
|
}
|
|
|
|
/**
|
|
* Base64 URL安全解码
|
|
*/
|
|
private function base64_url_decode($base64_url_string)
|
|
{
|
|
return base64_decode(str_replace(['*', '-', '_'], ['+', '/', '='], $base64_url_string));
|
|
}
|
|
|
|
/**
|
|
* 验证UserSig
|
|
* @param string $sig UserSig
|
|
* @param string $identifier 用户ID
|
|
* @param int $init_time 初始化时间
|
|
* @param int $expire_time 过期时间
|
|
* @param string $userbuf 用户权限buffer
|
|
* @param string $error_msg 错误信息
|
|
* @return bool 是否有效
|
|
*/
|
|
public function verifySig($sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg)
|
|
{
|
|
try {
|
|
$error_msg = '';
|
|
$compressed_sig = $this->base64_url_decode($sig);
|
|
$pre_level = error_reporting(E_ERROR);
|
|
$uncompressed_sig = gzuncompress($compressed_sig);
|
|
error_reporting($pre_level);
|
|
|
|
if ($uncompressed_sig === false) {
|
|
throw new \Exception('gzuncompress error');
|
|
}
|
|
|
|
$sig_doc = json_decode($uncompressed_sig, true);
|
|
if ($sig_doc === false) {
|
|
throw new \Exception('json_decode error');
|
|
}
|
|
|
|
if ($sig_doc['TLS.identifier'] !== $identifier) {
|
|
throw new \Exception('identifier dosen\'t match');
|
|
}
|
|
|
|
if ($sig_doc['TLS.sdkappid'] != $this->sdkappid) {
|
|
throw new \Exception('sdkappid dosen\'t match');
|
|
}
|
|
|
|
$sig = base64_decode($sig_doc['TLS.sig']);
|
|
if ($sig === false) {
|
|
throw new \Exception('sig base64_decode error');
|
|
}
|
|
|
|
$init_time = $sig_doc['TLS.time'];
|
|
$expire_time = $sig_doc['TLS.expire'];
|
|
|
|
$curr_time = time();
|
|
if ($curr_time > $init_time + $expire_time) {
|
|
throw new \Exception('sig expired');
|
|
}
|
|
|
|
$userbuf_enabled = false;
|
|
$base64_userbuf = '';
|
|
if (isset($sig_doc['TLS.userbuf'])) {
|
|
$base64_userbuf = $sig_doc['TLS.userbuf'];
|
|
$userbuf = base64_decode($base64_userbuf);
|
|
$userbuf_enabled = true;
|
|
}
|
|
|
|
$sigCalculated = $this->hmacsha256($identifier, $init_time, $expire_time, $base64_userbuf, $userbuf_enabled);
|
|
|
|
if ($sig != $sigCalculated) {
|
|
throw new \Exception('verify failed');
|
|
}
|
|
|
|
return true;
|
|
} catch (\Exception $ex) {
|
|
$error_msg = $ex->getMessage();
|
|
return false;
|
|
}
|
|
}
|
|
}
|