JWT是基于Json的开放标准,其定义了安全、紧凑、自包含的信息交换协议
优点
- 跨平台、跨域、轻量级的传输
- 可用于无状态的 身份认证、信息交换
- JWT中的载荷信息是可信的(因为签名的存在)
- 广泛用于分布式系统的SSO单点登录
- 在
OAUTH2
中引入JWT
能极大的简化认证流程- 授权服务器不需要维护
Token
存储 - 资源服务器也不必要求
Token
检查 - 减少了服务间的
HTTP
通信
- 授权服务器不需要维护
缺点
JWT
中存储信息如果过多很容易造成Token
过大(可通过jti
换取Redis
集中存储中的用户信息 解决该问题)
组成
JWT
由以下三部分Json
数据的Base64Url
密文,点号拼接而成
Headers
:包括ALGORITHM、TOKEN TYPE
PAYLOAD
:数据载荷,包括了三类claim
信息Reserved claims
预定义信息(包括iss签发者
、exp过期时间
、sub请求者
、aud接收者
、nbf起效时间
、iat签发时间
、jti唯一标识
)Public claims
自定义信息Private claims
订阅方和接受方的协议信息
Signature
:签名(可选HS256(对称加密)
、RS256(非对称加密)
两种签名算法)
HMACSHA256( #HS256签名算法
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
使用
HTTP
头部带上Token
信息
Authorization: Bearer jwt_token
Apache配置
Apache
默认丢弃结构特殊、非base64
编码的Authorization
头部,所以需要额外配置下
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
Laravel JWT-Auth
## 安装 ##
composer require tymon/jwt-auth:0.5.*
#注册
Tymon\JWTAuth\Providers\JWTAuthServiceProvider
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth'
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory'
#发布配置
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
#生成秘钥
php artisan jwt:generate
## 配置 ##
- secret 签名秘钥
- ttl token生存时间/min
- refresh_ttl token刷新生存时间/min
- algo token签名算法(维持默认即可)
- user User模型名字空间
- identifier 对应于token subject claim的User模型标识
- required_claims token中必须携带的chaim
- blacklist_enabled 若为false则刷新令牌后老令牌还是不会失效
## 签发令牌 ##
# 1. 快捷签发 #
$customClaims = [...] #尽量控制chaim信息量以防token过大
$token = JWTAuth::attempt($credentials [, $customClaims]) #尝试登陆并签发令牌
$token = JWTAuth::fromUser($user [, $customClaims]) #基于用户签发令牌
# 2. 底层自定义签发 #
$payload = JWTFactory::make($customClaims)
$payload = JWTFactory::sub(xxx)->aud(xxx)->foo($customClaims)->make()
$token = JWTAuth::encode($payload)
## 认证 ##
# 1. 客户端请求提供token #
- HTTP头部方式:Authorization: Bearer JWT_Token
- Query方式:?token=JWT_Token
# 2. 解析请求中的token #
$token = JWTAuth::getToken()
$user = JWTAuth::parseToken()->authenticate()
JWTAuth::setToken('xxx.yyy.zzz') #手动设置一个jwt
## 中间件 ##
protected $routeMiddleware = [
...
'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',
];
1. GetUserFromToken中间件 检查并解析token,否则抛出异常
- tymon.jwt.absent
- tymon.jwt.expired
- tymon.jwt.invalid
- tymon.jwt.user_not_found
- tymon.jwt.valid
2. RefreshToken中间件 每次请求刷新token