## JWT长什么样?
JWT是由三段信息构成的,将这三段信息文本用`.`链接一起就构成了Jwt字符串。就像这样:
~~~
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
~~~
## JWT的构成
### 1. 头部(header),
jwt的头部承载两部分信息:
> * 声明类型[,这里是jwt
> * 声明加密的算法 通常直接使用 HMAC SHA256
完整的头部就像下面这样的JSON:
~~~bash
{
'typ': 'JWT',
'alg': 'HS256'
}
~~~
然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.
~~~
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
~~~
### 2. 第二部分载荷(payload,),
载荷就是存放有效信息的地方。
>* 标准中注册的声明
>* 公共的声明
>* 私有的声明
**标准中注册的声明** (建议但不强制使用) :
* **iss**: jwt签发者
* **sub**: jwt所面向的用户
* **aud**: 接收jwt的一方
* **exp**: jwt的过期时间,这个过期时间必须要大于签发时间
* **nbf**: 定义在什么时间之前,该jwt都是不可用的.
* **iat**: jwt的签发时间
* **jti**: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
**公共的声明** :
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
**私有的声明** :
私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
定义一个payload:
~~~json
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
~~~
然后将其进行base64加密,得到Jwt的第二部分。
~~~
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
~~~
### playload 基本组成部分:
> 简单点:
~~~
$payload=[
'iss' => $issuer, //签发者
'iat' => $_SERVER['REQUEST_TIME'], //什么时候签发的
'exp' => $_SERVER['REQUEST_TIME'] + 7200 //过期时间
'uid'=>1111
];
~~~
> 复杂点:官方说法,三个部分组成(`Reserved claims`,`Public claims`,`Private claims`)
~~~
$token = [
#非必须。issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者。
"iss" => "http://maicaii.org",
#非必须。issued at。 token创建时间,unix时间戳格式
"iat" => $_SERVER['REQUEST_TIME'],
#非必须。expire 指定token的生命周期。unix时间戳格式
"exp" => $_SERVER['REQUEST_TIME'] + 7200,
#非必须。接收该JWT的一方。
"aud" => "http://maicaii.com",
#非必须。该JWT所面向的用户
"sub" => "admin",
# 非必须。not before。如果当前时间在nbf里的时间之前,则Token不被接受;一般都会留一些余地,比如几分钟。
"nbf" => 50000,
# 非必须。JWT ID。针对当前token的唯一标识
"jti" => '222we',
# 自定义字段
"name" => "Gonggui",
# 自定义字段
"Phone" => "13222222222",
];
~~~
### 3. 第三部分是签证(signature).
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
* header (base64后的)
* payload (base64后的)
* secret
这个部分需要base64加密后的header和base64加密后的payload使用`.`连接组成的字符串,然后通过header中声明的加密方式进行加盐`secret`组合加密,然后就构成了jwt的第三部分。
~~~csharp
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
~~~
将这三部分用`.`连接成一个完整的字符串,构成了最终的jwt:
~~~csharp
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
~~~
**注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。**
### 如何应用
一般是在请求头里加入`Authorization`,并加上`Bearer`标注:
~~~bash
fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
~~~
- 序言
- ThinkPHP官方资源
- 术语
- 根目录
- php术语
- jwt
- 下载jwt
- 认识jwt
- 生成token
- 验证token
- lcobucci/jwt
- 安装
- 配置
- 生成token
- 解析令牌
- 验证令牌
- 扩展库jwt
- thinkPHP使用lcobucci/jwt
- phpmailer
- PHPMailer的使用
- phpMailer config
- 短信验证吗
- 阿里云短信验证码发送类
- 权限管理
- 基于thinkphp6.0
- 通用函数
- 密码加密
- 数组
- 数据库
- 查询数据
- 添加数据
- 删除数据
- 批量删除
- 更新数据
- 请求流程
- thinkphp6安装
- thinkphp6目录介绍
- 单应用
- 多应用
- 配置文件
- 模型,模板与Model的区别
- .env介绍
- 入口文件
- 控制器
- model层
- 视图层
- common公共函数
- 路由
- 命令行
- 常用thinkphp函数和方法
- 高德地图i定位城市
- 更新日志