JWT由三个部分组成:header.payload.signature

以下示例以JWT官网为例header部分:

{ \公众alg\"大众: \"大众HS256\"大众, \"大众typ\"大众: \"大众JWT\公众}

对应base64UrlEncode编码为:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

解释:该字段为json格式。
alg字段指定了天生signature的算法,默认值为HS256,typ默认值为JWT

phphashhmacphp 后端实现JWT认证办法 RESTful API

payload部分:

{ \"大众sub\"大众: \"大众1234567890\"大众, \公众name\公众: \"大众John Doe\"大众, \公众iat\"大众: 1516239022}

对应base64UrlEncode编码为:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

解释:该字段为json格式,表明用户身份的数据,可以自己自定义字段,很灵巧。
sub 面向的用户,name 姓名 ,iat 签发韶光。
例如可自定义示例如下:

{ \"大众iss\"大众: \"大众admin\"大众, //该JWT的签发者 \"大众iat\"大众: 1535967430, //签发韶光 \公众exp\"大众: 1535974630, //过期韶光 \公众nbf\公众: 1535967430, //该韶光之前不吸收处理该Token \"大众sub\"大众: \"大众www.admin.com\公众, //面向的用户 \公众jti\"大众: \"大众9f10e796726e332cec401c569969e13e\"大众 //该Token唯一标识}signature部分:

HMACSHA256( base64UrlEncode(header) + \"大众.\公众 + base64UrlEncode(payload), 123456)

对应的署名为:keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

终极得到的JWT的json为(header.payload.signature):eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

解释:对header和payload进行base64UrlEncode编码后进行拼接。
通过key(这里是123456)进行HS256算法署名。

JWT利用流程初次登录:用户初次登录,输入用户名密码密码验证:做事器从数据库取出用户名和密码进行验证天生JWT:做事器端验证通过,根据从数据库返回的信息,以及预设规则,天生JWT返还JWT:做事器的HTTP RESPONSE中将JWT返还带JWT的要求:往后客户端发起要求,HTTP REQUESTHEADER中的Authorizatio字段都要有值,为JWT做事器验证JWT

PHP如何实现JWT

作者利用的是PHP 7.0.31,不废话,直接上代码,新建jwt.php,复制粘贴如下:

<?php/ PHP实现jwt /class Jwt { //头部 private static $header=array( 'alg'=>'HS256', //天生signature的算法 'typ'=>'JWT' //类型 ); //利用HMAC天生信息择要时所利用的密钥 private static $key='123456'; / 获取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) { $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; //署名验证 if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign) return false; $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY); //签发韶光大于当前做事器韶光验证失落败 if (isset($payload['iat']) && $payload['iat'] > time()) return false; //过期韶光小宇当前做事器韶光验证失落败 if (isset($payload['exp']) && $payload['exp'] < time()) return false; //该nbf韶光之前不吸收处理该Token if (isset($payload['nbf']) && $payload['nbf'] > time()) 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 = 'HS256') { $alg_config=array( 'HS256'=>'sha256' ); return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true)); }} //测试和官网是否匹配begin $payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022); $jwt=new Jwt; $token=$jwt->getToken($payload); echo \"大众<pre>\"大众; echo $token; //对token进行验证署名 $getPayload=$jwt->verifyToken($token); echo \"大众<br><br>\"大众; var_dump($getPayload); echo \"大众<br><br>\公众; //测试和官网是否匹配end //自己利用测试begin $payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));; $token_test=Jwt::getToken($payload_test); echo \"大众<pre>\公众; echo $token_test; //对token进行验证署名 $getPayload_test=Jwt::verifyToken($token_test); echo \"大众<br><br>\公众; var_dump($getPayload_test); echo \"大众<br><br>\"大众; //自己利用时候end