Laravel 用 JWT
JWT 全名 JSON Web Token
核心特点
紧凑格式:体积小,可通过URL、POST参数或HTTP头发送
自包含:包含所有必要信息,减少数据库查询
可验证:使用数字签名保证完整性
跨语言支持:几乎所有主流编程语言都有实现
JWT 的结构
由三部分组成,用点(.)分隔
Header.Payload.Signature
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vZGV2LXNob3AtbWFuYWdlLWFwaS5ob21lLmtsZi5jb20vc2hvcC1hcGkvbG9naW4iLCJpYXQiOjE3NDM0MTM1NjcsImV4cCI6MTc0MzQxNzE2NywibmJmIjoxNzQzNDEzNTY3LCJqdGkiOiJUZjR1OENxRHB0dW9vTHZpIiwic3ViIjoiNDgwMyIsInBydiI6IjI3ZjQxNDY0MDE3YjAwZTE5MmIxNzUyNjMzNGJlNmI1ZGIwYTBkOTQifQ.5uRxjozQ89eK-zSPLF8aV2bKxWXpsJRgR5XmU9sCy3Q
工作流程
用户登录:客户端发送凭据到认证服务器
验证凭据:服务器验证后生成JWT
返回JWT:服务器将JWT返回给客户端
存储JWT:客户端存储JWT(通常localStorage或cookie)
携带JWT:客户端在请求头中发送JWT
Authorization: Bearer <token>
验证JWT:服务器验证JWT并授权访问
laravel 安装配置JWT
1.安装JWT包
composer require tymon/jwt-auth
如果
Q
Laravel Composer could not install tymon/jwt-auth
A
composer require tymon/jwt-auth --ignore-platform-reqs
2.发布 JWT 配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此时会在 config 目录下生成 jwt.php 配置文件 app/config/jwt.php
3. 生成密钥
php artisan jwt:secret
这会在 .env 文件中添加 JWT_SECRET 注意的是 生产环境单独生成,为了安全
用户登录配置
1.用户模型 配置
创建用户模型文件
namespace App\Models;
User.php
必须继承 Authenticatable
实现 两个方法
getJWTIdentifier
getJWTCustomClaims
<?php
namespace App\Models;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class AdminUser extends Authenticatable implements JWTSubject
{
// ... 其他代码
/**
* 获取JWT标识符
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* 获取JWT自定义声明
*/
public function getJWTCustomClaims()
{
return [
'role' => $this->role, // 示例:添加用户角色到token
// 可以添加更多自定义声明
];
}
}
2.配置 auth.php
文件: config/auth.php
(2.1) 配置 Guard(守卫)
Guard 是 Laravel 认证系统的核心概念之一
定义了:
如何认证用户(使用什么驱动 driver)
session:传统的 web 应用认证方式(使用 cookies 和 session)
token:API 令牌认证(Laravel 自带的基础 token 认证)
jwt:使用 JWT 包提供的认证驱动
从哪里获取用户信息(使用什么 provider)
指定使用哪个用户提供者(在 providers 数组中定义)
'guards' => [
'api' => [
'driver' => 'jwt',
// 'provider' => 'users',
'provider' => 'Tymon\JWTAuth\Providers\LaravelServiceProvider::class', // 使用 作为 provider
'hash' => false,
],
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
(2.3) 配置 默认守卫
'defaults' => [
'guard' => 'admin-api',
'passwords' => 'users',
],
passwords 配置项用于定义密码重置功能的相关设置
3.登录控制器 开发
login控制器有两种验证机制:
手动验证登录,auth 生成token【常用】
自动验证登录,生成token【注意密码】
手动验证登录
// 获取用户实例
request->mobile)->first();
// 手动验证密码
if (!Hash::check(user->password)) {
return response()->json(['error' => '密码错误'], 401);
}
// 生成Token的三种方式(任选其一)
// 方式1:直接通过用户实例生成
user);
// 方式2:使用auth辅助函数
user);
// 或者自定义claims
$token = JWTAuth::claims([
'user_type' => $user->type,
'exp' => now()->addDays(30)->timestamp // 自定义过期时间
])->fromUser($user);
// 返回带Token的响应
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'user' => auth()->user(),
]);
上述就是登录验证 和 获取token 分离
auth 为laravel的认证系统,使用默认守卫进行生成token
auth()->user() 可获取到登录的用户信息
自动验证登录
// 验证输入
request->all(), [
'mobile' => 'required|string|size:11', // 假设手机号是11位
'password' => 'required|string|min:6',
]);
if ($validator->fails()) {
return response()->json([
'status' => 'error',
'message' => '参数验证失败',
'errors' => $validator->errors()
], 422);
}
// 使用手机号作为登录凭证
request->only('mobile', 'password');
mobile, 'password' => $password, 'state' => 1]);
if($token){
$user = Auth::guard('api')->user();
return $this->success('登录成功', [
'token' => $token,
'user' => $user,
]);
}else{
return $this->error('您输入的账号或密码错误', 103);
}
使用 attempt 方法时,需要注意你的密码是否是用 Bcrypt 算法哈希
如果不是,则会有以下报错 This password does not use the Bcrypt algorithm.
原因是 Laravel 默认认证系统 Auth(包括 attempt() 方法)强制要求使用 Bcrypt 算法,只有Bcrypt 算法生成的密码,才能验证通过。
通过在 Hash Facade 上调用 make 方法来哈希密码 Hash::make($request->newPassword)
小结下:
自动验证要求比较严格
正常情况下 手动验证 然后生成token
目前的遇到的验证,账号密码,手机号验证码等等。手动验证,灵活一点
.中间件 补充
目录:app/Http/Middleware/UserCheckToken.php
<?php
namespace App\Http\Middleware;
use App\Http\Trait\ResponseJson;
use Closure;
use Tymon\JWTAuth\Facades\JWTAuth;
class UserCheckToken
{
use ResponseJson;
public function handle(next)
{
try{
$user = auth()->user();
if(!$user){
return $this->error('用户未找到', 401);
}
}
catch(\Exception $e){
return $this->error('Token 验证失败', 401);
}
return request);
}
}
创建中间件 UserCheckToken
auth()->user() 的作用
验证请求携带有效的 JWT Token(Authorization: Bearer xxx)
JWT 会自动解析 Token 并还原用户信息
注意
同一次请求中多次调用 auth()->user() 不会重复查询数据库,第一次查询数据库,第二次返回内存缓存
此缓存仅持续到当前 HTTP 请求结束,下次请求会重新解析 Token
6. 路由配置中间件
Route::middleware([UserCheckToken::class])->group(function(){
Route::get('/test', [TestController::class, 'index']);
});
将需要验证登录信息的接口,放在此中间件下即可。
即完整的用Jwt 实现用户的登录
里面有很多的知识点都可以进行扩展,可以实现很多强大的,自定义的需求