Json web token
简称JWT,一个健壮令牌标准-RFC7519。
JWT由三部分组成:
header
payload
VERIFY SIGNATURE
header
&payload
用base64编码,中间用.
隔开,重要的是VERIFY SIGNATURE
,使用HMAC SHA-256算法生成摘要,具体为
#伪代码
HMACSHA256(
base64encode(header) + "." + base64Encode(payload) + '.' +secret
)
php中hs256算法:
//algo指定为sha256,数据放data,screat为key
string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )
secret
存服务器端,别泄露了。具体了解可参考:JWT.io
Laravel + jwt
这里Token生成的算法及验证就确定下来,和laravel 5.2
搭配使用如下:
基本配置
1.安装:composer require tymon/jwt-auth 0.5.*
2.config/app.php
中:
-
provider
增加Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class
-
aliases
增加'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class
3.发布相应配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
执行完命令后在config/
下会新增jwt配置文件jwt.php
:
//file:jwt.php
/*
|--------------------------------------------------------------------------
| JWT Authentication Secret (进行加密算法的时候的secret,这里32位)
|--------------------------------------------------------------------------
*/
'secret' => env('JWT_SECRET', 'ZD23ADFVKSKSDFSDJFKDFDFVsafaa12a'),
/*
|--------------------------------------------------------------------------
| JWT time to live (token有效期,单位分钟)
|--------------------------------------------------------------------------
| Defaults to 1 hour
| 1 hour = 60 minutes
*/
'ttl' => 60,
/*
|--------------------------------------------------------------------------
| Refresh time to live (刷新token时间,单位分钟)
|--------------------------------------------------------------------------
| Defaults to 2 weeks
| 2 weeks = 20160 minute
*/
'refresh_ttl' => 20160,
/*
|--------------------------------------------------------------------------
| JWT hashing algorithm (token签名算法)
|--------------------------------------------------------------------------
*/
'algo' => 'HS256',
/*
|--------------------------------------------------------------------------
| User Model namespace (指向User模型的命名空间路径)
|--------------------------------------------------------------------------
*/
'user' => 'App\Models\User',
/*
|--------------------------------------------------------------------------
| User identifier (用于从token的sub中获取用户)
|--------------------------------------------------------------------------
|
*/
'identifier' => 'id',
/*
|--------------------------------------------------------------------------
| Required Claims (必须出现在token的payload中的选项,否则会抛出TokenInvalidException异常)
|--------------------------------------------------------------------------
|
*/
'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'],
/*
|--------------------------------------------------------------------------
| Blacklist Enabled (如果该选项被设置为false,那么我们将不能废止token,即使我们刷新了token,前一个token仍然有效)
|--------------------------------------------------------------------------
*/
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
/*
|--------------------------------------------------------------------------
| Providers (完成各种任务的具体实现,有需求的情况写可重写)
|--------------------------------------------------------------------------
*/
'providers' => [
'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',
'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter',
'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter',
'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter',
],
];
4.最后生成密钥secret,写入config/jwt.php
中JWT_SECRET
的value
php artisan jwt:generate
生成token
1.控制器中创建token,使用orm获取用户对象:
$userObj = User::where('email',$username)->first();
$res['token'] = JWTAuth::fromUser($userObj);
2.客户端获取到token,可写入localstorage
,正常会话周期每次请求带上,token放入header中:Authorization : Bearer {token}
,这里的bearer
有持票人的意思,token
两边的{}
必须有。
在apache下会有header被丢弃的情况,apache下得写配置
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
验证
因为接口多,放到路由群组用中间件过滤(中间件姿势如使用不正确请指出):
1.执行php artisan make:middleware verifyToken
,在app\Http\Middleware\verifyToken.php
会生成verifyToken前置中间件,填充代码如下:
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class verifyToken
{
/**
* 请求前置中间件
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
try {
if (!JWTAuth::parseToken()->authenticate()) {
return response()->json(['user_not_found'], 404);
}
} catch (TokenExpiredException $e) {
//toke失效,response code可自定义
return response()->json(['token_expired'], 405);
} catch (TokenInvalidException $e) {
return response()->json(['token_invalid'], $e->getStatusCode());
} catch (JWTException $e) {
return response()->json(['token_absent'], $e->getStatusCode());
}
return $next($request);
}
}
2.app\Http\Kernel.php
中在routeMiddleware
处注册中间件,
'verifyToken' => 'App\Http\Middleware\verifyToken'
3.路由群组中使用:
//群组中中间件可以用多个,用数组传入即可
//这里的fetchResponse是后置中间件,用于包装供cors跨域的几个header
Route::group(['middleware' => ['fetchResponse','verifyToken']],function(){
Route::match(['POST','OPTIONS'],'someDo','someController@someFunc');
})
4.客户端可根据响应码不同进行处理。完。
参考链接:
1.Github jtw-auth
2.Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证 - laravel学院
3.JWT安全问题-翻译 2015年
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。