jwt安装
1
| composer require tymon/jwt-auth
|
jwt配置
1、发布配置文件
1
2
| # 这条命令会在 config 下增加一个 jwt.php 的配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
|
2、生成加密密钥
1
2
| # 这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar
php artisan jwt:secret
|
3、更新你的模型
如果你使用默认的 User 表来生成 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
42
43
44
45
46
47
48
| # 原来的 User
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
// ... code ...
}
## 增加的代码
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasApiTokens, HasFactory, Notifiable;
// ... code ...
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
|
4、注册两个 Facade
这两个 Facade 并不是必须的,但是使用它们会给你的代码编写带来一点便利。
1
2
3
4
5
6
7
8
9
10
11
| <?php
return [
...
'aliases' => [
...
// 添加以下两行
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],
]
|
5、修改 auth.php
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
| <?php
return [
// 开发接口,设置默认 guard 为 api
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
// 这里增加 guard api 并设置验证使用 jwt
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
...
]
|
6、创建 token 控制器
1
| php artisan make:controller Api/v1/AuthController
|
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| <?php
namespace App\Http\Controllers\Api\v1;
use App\Http\Controllers\Controller;
use Tymon\JWTAuth\Facades\JWTAuth;
/**
* @group auth 登陆相关接口
*
* <aside class="warning">用户登陆</aside>
*/
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
* 要求附带 name 和 password(数据来源users表)
*
* @return void
*/
public function __construct()
{
// 这里额外注意了:官方文档样例中只除外了『login』
// 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
// 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
// 不过刷新一次作废
$this->middleware('auth:api', ['except' => ['login', 'logout']]);
// 另外关于上面的中间件,官方文档写的是『auth:api』
// 但是我推荐用 『jwt.auth』,效果是一样的,但是有更加丰富的报错信息返回
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
...
}
|
7、注册路由
1
2
3
4
5
6
7
8
9
| <?php
Route::group([
'prefix' => 'auth'
], function ($router) {
Route::post('login', [\App\Http\Controllers\Api\v1\AuthController::class, 'login']);
...
});
|
实现 jwt token 过期时间动态设置(记住我)
jwt token 的过期时间在 config/jwt.php 中可以配置,默认1小时。
而实际项目中,前端登陆时有【记住我】这个功能,勾选后需要过期时间设置为7天。最终找到解决办法如下:
- App\Http\Controllers\Api\v1\AuthController::login
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
|
/**
* login 用户登录
*
* Get a JWT via given credentials.
* @bodyParam name string required 用户名。
* @bodyParam password string required 密码(不用加密)。
* @bodyParam remember bool 记住我(自动登录)。
*
* @return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['name', 'password']);
if (request(['remember'])) {
JWTAuth::factory()->setTTL(60 * 24 * 7);
}
$token = JWTAuth::attempt($credentials);
if (! $token) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
|
软件版本:laravel 8.54
参考资料