Laravel使用JWT

Laravel使用JWT

前言

laravel使用JWT有两种方法,一中是使用内置的Auth结合JWT定义的中间件进行认证,这种方法laravel社区有很多教程,这里不再细说,谈谈如何使用自定义JWT来完成用户认证

JWT-oath

安装

1
2
3
#使用composer安装jwt-oath扩展
#当然也可以写进composer.json文件中
composer require tymon/jwt-auth

生成加密密匙

1
2
3
# 这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar
#注意.env文件默认是不会上传git的,为了你的同伴也可以正常使用认证,需要在.env.example中手动添加相同的字段
php artisan jwt:secret

注册两个 Facade

这两个 Facade 并不是必须的,但是使用它们会给你的代码编写带来一点便利。

config/app.php

1
2
3
4
5
6
'aliases' => [
...
// 添加以下两行
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],

修改 auth.php

config/auth.php

1
2
3
4
5
6
7
8
9
10
11
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'jwt', // 原来是 token 改成jwt
'provider' => 'users',
],
],

处理流程

mark

使用方法

生成

1
2
3
4
5
6
7
8
9
10
11
12
<?php
//自定义的载荷填充
$customClaims = [
'iss' => "http://market.sky31.com",
'share' => md5($stu_id),
];
//利用JWT工厂类生成根据自定义的载荷生成payload
$payload = \JWTFactory::customClaims($customClaims)->make();
//调用Auth类的encode方法就可以生成token
$token = \JWTAuth::encode($payload);
//注意,此处的token是一个类,如何直接添加进response()->json()中将会报错,所以强制转换为String便可以当成字符床正常使用了
return (string)$token;

验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
//认证可以写在中间件中
//首部use添加JWT的所有异常类
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

//一定要使用try catch版快来验证token,token的验证失败,过期等等异常都是throw一个异常,不捕获异常程序直接死掉了,且错误信息不可以定义,就会导致代码不严谨
try {
//定义一个Auth类来验证token,首先将传过来的token绑定在类中
$token = \JWTAuth::setToken($data['token']);
//调用以下方法可以获取token中载荷的数据来使用
$user_id=$token->payload()->get()['user_id'];
//验证token,正确就会取出其中的载荷返回一个只含有载荷的对象,
//失败就会抛出异常,失败的原因有许多,过期,数据格式不对,整个JWT过期
$token->checkOrFail();
//还有一个$token()->check方法可以验证token,返回值为bool,验证失败不会抛出异常而是返回false
//捕获过期异常然后去刷新过期时间
} catch (TokenExpiredException $e) {
try {
//刷新token,返回值是更新过期时间的新token
$new_token=$token->refresh();
//更新数据库中的token
$user= User::query()->where('user_id',$user_id)->first();
$user->token=$new_token;
$user->save();
//将新token设置在request的参数中传给下一个路由
$request->request->set("token",$new_token);
//如果刷新不了,也过期了就返回错误码让用户重新登录
}catch (TokenExpiredException $e){
//msg是我自定义的用来返回json的,不用管
return msg(3,__LINE__);
}
//token格式错误
} catch (TokenInvalidException $e) {
return msg(403,$e->getMessage());
}catch (JWTException $e) {
return msg(403,$e->getMessage());
}
//将request传给下下一个路由,到这里认证便成功了
return $next($request);

说明

JWT-oath扩展会在config目录下生成一个jwt.php,里面定义了JWT的相关配置

**注意:**这个扩展有两种过期方式,一种的token有效期,时间短,过期了需要刷新,一种是刷新有效期,时间长,只要在有效期内拿不在黑名单的旧token来刷新就可以,时间一长一短可以一定程度上防止token盗用

常用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//jwt有效期,默认是60分钟,单位是分钟
JWT_TTL
//jwt的刷新有效期,单位是分钟,默认是20160(14天)
JWT_REFRESH_TTL
//注意以上两个时间不可以用60*24这种格式,需要设置为120这样的整数
//必须填充的载荷,在你自己设定载荷的时候必须全部手动填充,不然会报错,无法生成,不想自定义的可以注释掉
'required_claims' => [
'iss',
// 'iat',
// 'exp',
// 'nbf',
// 'sub',
// 'jti',
],
//iss默认是使用用于请求的api路径
//设置黑名单,当为false时,刷新后生成新token,旧token仍然可以用
//true验证时就会抛出黑名单异常信息
blacklist_enabled

建议是修改.env中的环境变量,不要修改jwt.php文件,因为jwt.php文件中的配置项大都是从.env中获取的,没有获取到会用默认值