JWT - JsonWebToken

原创
2017/06/17 14:37
阅读数 338

交互过程

  1. 客户端通过账号密码向服务端认证申请JWT
  2. 服务端认证通过后签发一个带认证信息和签名的JWT
  3. 客户端在后续请求的Http头部Authorization域提供JWT以供服务端鉴权
  4. 服务端提取请求头部的JWT,签名校验无误后解析JWT中的认证信息,最后响应客户端请求内容

优点

  • 认证信息无状态自包含(减少数据库查询)、可信任(签名确保认证信息可信),支持跨界传输(实现SSO单点登录)
  • OAuth2使用JWT能极大简化鉴权过程:授权服务器不需要Token存储,资源服务器不需要Token查询,减少数据库调用及服务间HTTP通信

缺点

  • JWT携带信息过多可能导致网络传输加重(jti换取Redis中用户信息可解决该问题)
  • JWT验签会增加服务端CPU开销
  • 服务端无法主动吊销JWT

结构

  1. Headers Json头部声明
{
	"alg": "HS256",  //签名算法,HS256对称加密 或 RS256非对称加密
	"typ": "JWT" //令牌类型
}
  1. Payload Json数据载荷
{
//Registered claims预定义字段(可选)
“iss”: "签发者",
"sub": "请求者",
"aud": "接收者",
"exp": "过期时戳",
"iat": "签发时戳",
"nbf": "起效时间",
"jti": "唯一标识",

//Public claims自定义字段(可选)
#可插入一些非敏感的用户认证信息

//Private claims通信双方信息共享字段(可选)
}
  1. Signature使用Header声明的算法进行签名
//HS256签名示例
Signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), 服务端256位的secret私钥 )
  1. JWT = base64UrlEncode(Header) . base64UrlEncode(Payload) . Signature

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
展开阅读全文
打赏
0
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部