博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jwt原理与应用-php
阅读量:3987 次
发布时间:2019-05-24

本文共 6420 字,大约阅读时间需要 21 分钟。

官网:https://jwt.io/

官网有案例测试。

jwt-framework

github:https://github.com/web-token/jwt-framework
文档:https://web-token.spomky-labs.com/
composer require web-token/jwt-framework

为什么要使用JWT

JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。

它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。它具备两个特点:

简洁(Compact):可以通过URL, POST 参数或者在 HTTP header 发送,因为数据量小,传输速度快

自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库

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

1、header部分:

{  "typ": "JWT",  "alg": "HS256"}

对应base64UrlEncode编码为:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

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

2、payload部分:

{  "iss": "xxxx",//该JWT的签发者  "iat": 1569746556,//签发时间  "exp": 1601282556,//过期时间  "nbf": 1569746556,//该时间之前不接收处理该Token  "jti": "NSiLlGKANgTRA9WD",//该Token唯一标识  "sub": xxxxxxx,//面向的用户,比如用户id  "prv": "f6b71549db8c2c42b75827aa44f02b7ee529d24d"}

对应base64UrlEncode编码为:eyJpc3MiOiJodHRwOi8vMTcyLjMxLjIwNS43MC91Yy91Y2VudGVyL3JlQmluZGluZyIsImlhdCI6MTU2OTc0NjU1NiwiZXhwIjoxNjAxMjgyNTU2LCJuYmYiOjE1Njk3NDY1NTYsImp0aSI6Ik5TaUxsR0tBTmdUUkE5V0QiLCJzdWIiOjkzMjYwOSwicHJ2IjoiZjZiNzE1NDlkYjhjMmM0MmI3NTgyN2FhNDRmMDJiN2VlNTI5ZDI0ZCJ9

说明:该字段为json格式,表明用户身份的数据,可以自己自定义字段,很灵活。

3、signature部分:

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), 123456)

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

对应的签名为:wwTa9XRLydYmrjCOgiB4Wq1_rzGZ4sVeLg3NZVr0SaA

4、最终得到的结果就是三段的拼接:header.payload.signature,即

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTcyLjMxLjIwNS43MC91Yy91Y2VudGVyL3JlQmluZGluZyIsImlhdCI6MTU2OTc0NjU1NiwiZXhwIjoxNjAxMjgyNTU2LCJuYmYiOjE1Njk3NDY1NTYsImp0aSI6Ik5TaUxsR0tBTmdUUkE5V0QiLCJzdWIiOjkzMjYwOSwicHJ2IjoiZjZiNzE1NDlkYjhjMmM0MmI3NTgyN2FhNDRmMDJiN2VlNTI5ZDI0ZCJ9.wwTa9XRLydYmrjCOgiB4Wq1_rzGZ4sVeLg3NZVr0SaA

5、使用

一般将生成的jwt串放在请求头的 Authorization 中传递,服务端来验证。

在使用 JWT 时需要注意以下事项:

  1. JWT 默认不加密,如果要写入敏感信息必须加密,可以用生成的原始令牌再次对内容进行加密;
  2. JWT 无法使服务器保存会话状态,当令牌生成后在有效期内无法取消也不能更改;
  3. JWT 包含认证信息,如果泄露了,任何人都可以获得令牌所有的权限;因此 JWT 有效期不能太长,对于重要操作每次请求都必须进行身份验证。

代码:

'HS256', //生成signature的算法 'typ' => 'JWT' //类型 ]; // payload private $payload; // 过期时间 private $ttl = 10;// 10s private $refreshTtl = 7200; //使用HMAC生成信息摘要时所使用的密钥 private $key = '123456'; // 是否开启黑名单,开启后在校验token的时候会检查黑名单,影响性能,但是安全。 private $openBlackList = false; public function __construct() { } // 设置载荷 private function setPayload($pay = []) { $this->payload = [ "iss" => "jwt_admin",//该JWT的签发者 "iat" => time(),//签发时间 "exp" => time() + $this->ttl,//过期时间 "nbf" => time(),//该时间之前不接收处理该Token "jti" => md5(uniqid('JWT') . time()),//该Token唯一标识 "sub" => '',//面向的用户,比如用户id ]; $this->payload = array_merge($this->payload, $pay); } // 设置过期时间 public function setTtl($seconds) { $seconds = intval($seconds); if ($seconds > 0) { $this->ttl = $seconds; } } // 生成token public function getToken($payload) { $this->setPayload($payload); if (is_array($this->payload)) { $base64header = $this->base64UrlEncode(json_encode($this->header, JSON_UNESCAPED_UNICODE)); $base64payload = $this->base64UrlEncode(json_encode($this->payload, JSON_UNESCAPED_UNICODE)); $signature = $this->signature($base64header . '.' . $base64payload, $this->key, $this->header['alg']); $token = $base64header . '.' . $base64payload . '.' . $signature; return $token; } else { return false; } } // 验证token public function verifyToken($Token) { $tokens = explode('.', $Token); if (count($tokens) != 3) return false; list($base64header, $base64payload, $sign) = $tokens; //获取jwt算法 $base64decodeheader = json_decode($this->base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY); if (empty($base64decodeheader['alg'])) return false; //签名验证 if ($this->signature($base64header . '.' . $base64payload, $this->key, $base64decodeheader['alg']) !== $sign) return false; $payload = json_decode($this->base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY); // 判断黑名单 $payload['jti'] if($this->openBlackList){ } //签发时间大于当前服务器时间验证失败 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; } // 刷新token延长过期时间 public function refreshToken($token){ } /** * 当token泄露,或者注销登录,将token加入黑名单,使用redis存储,key的过期时间应大于token的过期时间。 * 一般将payload中的jti作为key,因为jti是唯一标识,value可以设置空,因为并不需要。 */ public function addBlackList(){ if($this->openBlackList){ } } /** * base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现 * 将 +/ 替换成 -_ * 将 = 删除 * @param string $input 需要编码的字符串 * @return string */ private function base64UrlEncode($input) { return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); } /** * base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现 * @param string $input 需要解码的字符串 * @return bool|string */ private function base64UrlDecode($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 function signature($input, $key, $alg = 'HS256') { $alg_config = array( 'HS256' => 'sha256' ); return $this->base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true)); }}// 测试加密$payload = array('sub' => '1234567890', 'name' => 'John Doe');$jwt = new Jwt;$token = $jwt->getToken($payload);echo $token.PHP_EOL;//对token进行验证签名$getPayload = $jwt->verifyToken($token);var_dump($getPayload);echo PHP_EOL;

转载地址:http://jgxui.baihongyu.com/

你可能感兴趣的文章
嵌入式linux 开发板 dhcp ip
查看>>
/etc/resolv.conf
查看>>
/etc/hosts
查看>>
container_of()传入结构体中的成员,返回该结构体的首地址
查看>>
linux sfdisk partition
查看>>
ipconfig,ifconfig,iwconfig
查看>>
opensuse12.2 PL2303 minicom
查看>>
电平触发方式和边沿触发的区别
查看>>
中断函数中不能调用ioremap()!!!!!!!
查看>>
网络视频服务器移植
查看>>
Encoding Schemes
查看>>
EFM32TG222F32连接JLink V8问题
查看>>
Keil问题
查看>>
移植QT
查看>>
交叉编译qt-everywhere-4.8.4
查看>>
tslib qt4 segmentation fault
查看>>
QT隐藏mouse
查看>>
求最短路径
查看>>
找到一个数组后面第一个大的数
查看>>
找到一个链表中倒数第k个数
查看>>