网站首页 > 技术文章 正文
一、JWT 简单介绍
JWT 全称 JSON Web Tokens ,是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。它的两大使用场景是:认证和数据交换。
以下步骤都是经过本人自研项目实践过,大家可以放心参考;
二、安装之前
主要使用的扩展及参考资料:
- PHP-Open-Source-Saver/jwt-auth
- JWT 完整使用详解
- JWT的介绍
- 官方安装指导文件
三、安装及配置
1)使用 composer 安装
composer require php-open-source-saver/jwt-auth
2)进行一些配置
2.1)发布配置文件
这条命令会在 config 下增加一个 jwt.php 的配置文件
php artisan vendor:publish --provider="PHPOpenSourceSaver\JWTAuth\Providers\LaravelServiceProvider"
2.2)生成加密密钥
这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar
php artisan jwt:secret
2.3)生成证书(可选)
这一步可不配置,但配置后生成的 Token 会根据证书文件来生成,更加安全;详细可看官方安装指导里的说明。
php artisan jwt:generate-certs
2.4)更新你的模型
如果你使用默认的 User 表来生成 Token,你需要在该模型下增加一段代码
app/Models/User.php
<?php
namespace App;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject # 这里别忘了加
{
use Notifiable;
// Rest omitted for brevity
/**
* 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 [];
}
}
2.5)注册两个 Facade
这两个 Facade 并不是必须的,但是使用它们会给你的代码编写带来一点便利。
config/app.php
'aliases' => [
...
// 添加以下两行
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],
如果你不使用这两个 Facade,你可以使用辅助函数 auth ()
auth () 是一个辅助函数,返回一个 guard,暂时可以看成 Auth Facade。
// 如果你不用 Facade,你可以这么写
auth('api')->refresh();
// 用 JWTAuth Facade
JWTAuth::parseToken()->refresh();
两个 Facede 常用可使用方法,可以看文章后面的附录。
2.6)修改 auth.php
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 原来是 token 改成jwt
'provider' => 'users',
],
],
2.7)创建 Auth 控制器
php artisan make:controller AuthController
app/Http/Controllers/AuthController.php
值得注意的是 Laravel 这要用 auth('api')。
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
* 要求附带email和password(数据来源users表)
*
* @return void
*/
public function __construct()
{
// 这里额外注意了:官方文档样例中只除外了『login』
// 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
// 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
// 不过刷新一次作废
$this->middleware('jwt.auth', ['except' => ['login']]);
// 另外关于上面的中间件,官方文档写的是『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 authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json(auth('api')->user());
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
/**
* Refresh a token.
* 刷新token,如果开启黑名单,以前的token便会失效。
* 值得注意的是用上面的getToken再获取一次Token并不算做刷新,两次获得的Token是并行的,即两个都可用。
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
四、JWT Token 详解
1)Token 创建
前面的 AuthController.php 中有两行展现了这一种 Token 的创建方法,即用用户所给的账号和密码进行尝试,密码正确则用对应的 User 信息返回一个 Token 。
但 Token 的创建方法不止这一种,接下来介绍 Token 的三种创建方法:
- 基于账密参数
- 基于 users 模型返回的实例
- 基于 users 模型中的用户主键 id
a)基于账密参数
这就是刚刚说的哪一种,贴出具体代码。
// 使用辅助函数
$credentials = request(['email', 'password']);
$token = auth()->attempt($credentials)
// 使用 Facade
$credentials = $request->only('email', 'password');
$token = JWTAuth::attempt($credentials);
b)基于 users 模型返回的实例
// 使用辅助函数
$user = User::first();
$token = auth()->login($user);
// 使用 Facade
$user = User::first();
$token = JWTAuth::fromUser($credentials);
c)基于 users 模型中的主键 id
// 使用辅助函数
$token = auth()->tokenById(1);
// 使用 Facade
源码中没找到
2)Token 的解析
a)解析 Token 到对象
只有 Facade 需要这样。
// 把请求发送过来的直接解析到对象
JWTAuth::parseToken();
b)获取 Token 中的 user 信息
// 辅助函数
$user = auth()->user();
// Facade
$user = JWTAuth::parseToken()->authenticate();
c)获取 Token
如果 token 被设置则会返回,否则会尝试使用方法从请求中解析 token ,如果 token 未被设置或不能解析最终返回 false。
// 辅助函数
$token = auth()->getToken();
// Facade
$token = JWTAuth::parseToken()->getToken();
更多方法可以看官方安装指南文件。
五、Token 的三个时间
一个 Token 一般来说有三个时间属性,其配置都在 config/jwt.php 内。
有效时间
有效时间指的的是你获得 Token 后,在多少时间内可以凭这个 Token 去获取内容,逾时无效。
// 单位:分钟
'ttl' => env('JWT_TTL', 60)
刷新时间
刷新时间指的是在这个时间内可以凭旧 Token 换取一个新 Token。例如 Token 有效时间为 60 分钟,刷新时间为 20160 分钟,在 60 分钟内可以通过这个 Token 获取新 Token,但是超过 60 分钟是不可以的,然后你可以一直循环获取,直到总时间超过 20160 分钟,不能再获取。
// 单位:分钟
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160)
宽限时间
宽限时间是为了解决并发请求的问题,假如宽限时间为 0s ,那么在新旧 token 交接的时候,并发请求就会出错,所以需要设定一个宽限时间,在宽限时间内,旧 Token 仍然能够正常使用。
// 宽限时间需要开启黑名单(默认是开启的),黑名单保证过期token不可再用,最好打开
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true)
// 设定宽限时间,单位:秒
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 60)
猜你喜欢
- 2025-06-10 开发程序不写代码,而是靠拼图?(制作拼图小游戏的c语言代码)
- 2025-06-10 moodle 开源的在线学习管理系统(LMS)部署
- 2025-06-10 用WordPress建站哪些插件会拖慢速度影响排名?
- 2025-06-10 3分钟短文:一看就是干货!Laravel迁移数据库
- 2025-06-10 如何让WordPress博客的投稿者也可以上传图片的方法
- 2025-06-10 Serverless 工程实践 | 快速搭建 Kubeless 平台
- 2025-06-10 腾讯云云函数部署laravel项目(github腾讯云函数部署)
- 2025-06-10 如何搭建内网服务器:详细教程(建立内网服务器)
- 2025-06-10 浅谈几种常见的分布式ID(分布式id生成算法)
- 2025-06-10 Wordpress建站教程:上传图片重命名,避免中文名影响SEO优化
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)