下面是完整的类的代码,使用也非常的简单,一个是getToken(),另一个是verifyToken()
class Jwt
{
//这个是头部
private static $header=array(
'alg' => 'HS256',//生成signature的算法
'typ' => 'JWT'//类型
);
//使用HMAC生成信息摘要时所使用的秘钥
private static $key = '123456';
/**
* 获取jwt token
* @param array $payload jwt荷载
* @return bool|string
*/
public static function getToken(array $payload){
if(is_array($payload)){
$base64header = self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));
$base64payload = self::base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
$base64signature = self::signature($base64header . '.' . $base64payload, self::$key, self::$header['alg']);
return $token = $base64header . '.' . $base64payload . '.' . $base64signature;
}else{
return false;
}
}
/**
* 验证token是否有效,默认值验证exp时间
* @param string $token 需要验证的token
* @return bool|mixed 如果正确,那么,将返回数组$payload
*/
public static function verifyToken(string $token){
$tokens = explode('.', $token);
if (count($tokens) != 3){
return false;
}
list($base64header, $base64payload, $sign) = $tokens;
//获取header部分
$base64decodeheader = json_decode(self::base64UrlDecode($base64header),true);
if (empty($base64decodeheader['alg'])){
return false;
}
//签名验证,就是将现成的$base64header和$base64payload重新加密一遍,看是不是等于$sing
$calc_sign = self::signature(
$base64header . '.' . $base64payload,
self::$key,
$base64decodeheader['alg'],
);
if ($calc_sign != $sign){
return false;
}
//获得payload
$payload = json_decode(self::base64UrlDecode($base64payload),true);
//核对过期时间是不是小于现在的时间,如果是,那就返回false
if (isset($payload['exp']) && $payload['exp'] < time()){
return false;
}
return $payload;
}
/**
* 首先用base64_encode编码,然后换掉+/=这3个符号
* 为什么不直接用urlEncode?
* 我觉得可能是为了减少运算吧,反正就这3个符号,没有更多。
* @param string $input 需要编码的字符串
* @return string 编码后的字符串
*/
private static function base64UrlEncode(string $input){
return str_replace('=','',strtr(base64_encode($input),'+/','-_'));
}
/**
* 解码由base64UrlEncode()编码的字符串
* @param string $input
* @return bool|string 解码后的字符串
*/
private static function base64UrlDecode(string $input){
$remainder = strlen($input) % 4;
if ($remainder) {
$addlen = 4 - $remainder;
$input .= str_repeat('=', $addlen); //差了几个=就补上几个等号
}
return base64_decode(strtr($input, '-_', '+/'));
}
/**
* HMACSHA256签名
* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
* @param string $key 秘钥
* @param string $alg 算法
* @return string 返回签名的编码后的字符串
*/
private static function signature(string $input, string $key, string $alg = 'HS256'){
$alg_config = array(
'HS256' => 'sha256'
);
$signature = hash_hmac($alg_config[$alg], $input, $key, true);
return self::base64UrlEncode($signature);
}
}
贴上我在ThinkPHP中的测试代码:
public function testToken(){
$payload = [
'exp' => time() + 9000,
'name' => 'user',
'jti' => '11111233'
];
return $token = Jwt::getToken($payload);
}
public function testToken2(){
$token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjUwMTk2NzIsIm5hbWUiOiLmsZ_niofniociLCJqdGkiOiIxMTExMTIzMyJ9.mgSMwnpHQiIlBYNGTphAsYWc2pTiygj1AhmQU_p1OBw';
$payload = Jwt::verifyToken($token);
dump($payload);
}
上面的代码是基于这个代码修改的(其实没有改多少,只是改了一些说明):https://www.jb51.net/article/146790.htm
网友评论