首先来一波jwt的深入了解
这一波内容是翻阅了各种资料,然后进行整合,得出了以下文章。
jwt是什么
JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。
jwt由什么组成
由三部分组成,分别是header.payload.signature
jwt官网地址
第二波jwt的分解
header(头部)
承载两部分信息:
1:声明类型,这里是jwt:
2:声明加密的算法 通常直接使用 HMAC SHA256 SHA512
完整的头部就像下面这样的JSON:
$header=array(
'alg'=>'HS512', //生成signature的算法,可更换
'typ'=>'JWT' //类型,可更换
);
payload(载荷:存放有效信息的地方)
一般包括以下这些,但是不强制
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
例如一会我给的例子中就只包括了login_user_key
格式如下:
{
"login_user_key":"11111111111111111111111"
}
signature(验证签证信息)
base64UrlEncode(header) + "." + base64UrlEncode(payload),secret
第三波 jwt的一般使用流程
- 初次登录:用户输入账号密码开始进行登录,并且进行密码验证
- 生成jwt:服务器验证通过了,然后开始生成jwt,并且返回给前端,其他所有接口将jwt作为头部或者其他进行传入。
- 验证jwt:服务器验证jwt是否正确,正确的话根据带回的信息再去处理自己的逻辑
- 备注:为了加强安全性,大家可以在其中加入前缀,后缀,验证段进行再次加密等形式
第四波 php实现jwt的代码
直接运行本代码段的tets即可
<?php
class LoginToken
{
//头部
private static $header=array(
'alg'=>'HS512', //生成signature的算法
'typ'=>'JWT' //类型
);
//使用HMAC生成信息摘要时所使用的密钥
private static $key='';
/**
* 获取jwt token
* @param array $payload jwt载荷 格式如下非必须
* [
* 'iss'=>'jwt_admin', //该JWT的签发者
* 'iat'=>time(), //签发时间
* 'exp'=>time()+7200, //过期时间
* 'nbf'=>time()+60, //该时间之前不接收处理该Token
* 'sub'=>'www.admin.com', //面向的用户
* 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
* ]
* @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));
$token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);
return $token;
}else{
return false;
}
}
/**
* 验证token是否有效,默认验证exp,nbf,iat时间
* @param string $Token 需要验证的token
* @return bool|string
*/
public static function verifyToken(string $Token){
$prefix_lenght = strlen(self::$token_prefix);
$Token = substr($Token, $prefix_lenght);
$tokens = explode('.', $Token);
if (count($tokens) != 3){
return false;
}
list($base64header, $base64payload, $sign) = $tokens;
//获取jwt算法
$base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
if (empty($base64decodeheader['alg'])){
return false;
}
//签名验证--如果是验证其他项目或者人生成的jwt,signature可能需要修改,因为很多人为了安全会多加几层验证或者修改验证方式,毕竟这层有点像摘要放篡改是一个道理。以下代码中的为标准的
if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign){
return false;
}
$payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
if(empty($payload['login_user_key'])){
return false;
}
return $payload;
}
/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现
* @param string $input 需要编码的字符串
* @return string
*/
private static function base64UrlEncode(string $input)
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
/**
* base64UrlEncode https://jwt.io/ 中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签名 https://jwt.io/ 中HMACSHA256签名实现
* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
* @param string $key
* @param string $alg 算法方式
* @return mixed
*/
private static function signature(string $input, string $key, string $alg = 'HS512'){
$alg_config=array(
'HS512'=>'sha512'
);
return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
}
private static function apiIsToken($token){
//先验证信息是否正确并且获取token
$getPayload=$this->verifyToken($token);
if($getPayload){
return $getPayload;
}else{
return false;
}
}
/*
*验证段
*/
public function test(){
$payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022);
$token=$this->getToken($payload);//注释1
echo "<pre>";
echo $token;
$token = '本处传入需要测试的jwt';//也可以注释这行代码 直接用注释1的token
$info = $this->apiIsToken($token);
var_dump($info);
}
}
第五波 jwt官网验证
去到官网按下图输入,用于多人之间相互对接时解决困难使用的
欢迎各位老铁踩踩