bkremenovic / eloquent-tokens
一个通用的Laravel包,用于管理和验证Eloquent模型相关令牌
Requires
- php: ^8.0
- ext-json: *
- ext-zlib: *
- laravel/framework: ^7.0|^8.0|^9.0|^10.0|^11.0
- nesbot/carbon: ^2.71.0 || ^3.0.0
Requires (Dev)
- nunomaduro/collision: ^7.8
- orchestra/testbench: ^8.21
README
本包的开发旨在解决Laravel中灵活高效的令牌管理系统长期需求。它支持多种驱动程序,节省空间,并为令牌处理提供多种有用的功能。
经过四个月的专注开发,我在生日之际宣布推出这个包,作为对出色的Laravel社区的特殊感谢。🎉
目录
安装指南
快速安装
通过Composer安装包
composer require bkremenovic/eloquent-tokens
Laravel的自动发现机制将自动检测服务提供者。
配置
-
发布并运行迁移
php artisan vendor:publish --provider="Bkremenovic\EloquentTokens\EloquentTokensServiceProvider" --tag="migrations" php artisan migrate
-
发布配置文件
php artisan vendor:publish --provider="Bkremenovic\EloquentTokens\EloquentTokensServiceProvider" --tag="config"
令牌驱动程序
Laravel Eloquent Tokens包提供了两种灵活的令牌管理驱动程序,每种驱动程序都具有独特的特性,以满足不同的需求和场景。
了解这两个驱动程序的优缺点对于做出明智的决定至关重要,选择合适的驱动程序对于确保您的令牌管理策略的有效性和效率至关重要。
无状态令牌驱动程序
此驱动程序利用Laravel的encrypt()
和decrypt()
函数,并通过在加密之前压缩数据来优化空间。
优点
- 空间效率:不消耗磁盘空间,非常适合生成大量令牌的应用程序。
- 批量黑名单:简化了无效化旧令牌的过程。
- 增强安全性:在数据泄露的情况下,由于令牌不存储,因此降低了风险。
局限性
- 依赖于APP_KEY:紧密绑定到Laravel的APP_KEY;对此的任何更改都会影响已发行的令牌。
- 无令牌跟踪:无法跟踪或审计先前发行的令牌。
- 令牌长度问题:包含大量数据的令牌可能变得过长,如果用于URL中可能会引起问题。
数据库令牌驱动程序
此驱动程序使用数据库存储来管理令牌。
优点
- 令牌可审计性:便于跟踪和列出所有已发行的令牌。
局限性
- 空间消耗:数据库空间使用量较高。
- 潜在安全风险:数据库中可见的令牌列表可能存在安全风险。
决策指南:选择合适的驱动程序
选择合适的驱动程序取决于各种因素,例如令牌生命周期、使用模式和管理工作偏好。
- 对于长期使用、高量使用:选择
StatelessTokenDriver
以节省数据库空间。 - 对于详细令牌管理:如果需要全面控制令牌,请选择
DatabaseTokenDriver
。
使用说明
实现特性
将HasEloquentTokens
特性添加到您的Eloquent模型中,以启用令牌功能
use Bkremenovic\EloquentTokens\Traits\HasEloquentTokens; class Project extends Model { use HasEloquentTokens; // ... model properties }
定义令牌类型
在getAllowedTokenTypes
方法中定义允许的令牌类型
public static function getAllowedTokenTypes(): array { return [ "INVITE_TOKEN", "ACCESS_TOKEN", // ... other types as per your needs ]; }
令牌管理
创建令牌
-
模型方法
$token = $model->createToken("INVITE_TOKEN")->getToken();
-
令牌外观
$token = Token::create($model, "INVITE_TOKEN")->getToken();
设置令牌过期时间、附加数据和指定驱动程序的可选方案,请见下方说明。
查询令牌
与Eloquent函数类似,此依赖提供两个用于查找/解析令牌的函数
- 标准查找:返回
TokenInstance
或null
。$tokenInstance = Token::find("eyJpdiI6Ik9FdFFqRmpxbXhh.....");
- 强制查找:返回
TokenInstance
。如果未找到,则抛出TokenNotFoundException
异常。$tokenInstance = Token::findOrFail("eyJpdiI6Ik9FdFFqRmpxbXhh.....");
删除令牌
删除Eloquent模型令牌有两种方式
-
通过在模型实例上调用
deleteTokens()
函数// This would delete/blacklist all tokens related to the $model (targeting both model class and model id) $model->deleteTokens();
-
通过在Token外观上调用
deleteBy
函数// This would delete/blacklist all tokens related to the $model (targeting both model class and model id) Token::deleteBy($model); // This would delete/blacklist all tokens related to the Project model (targeting model class) Token::deleteBy(null, Project::class);
deleteBy
函数在Token外观中的签名如下
function deleteBy( Model $model = null, string $modelClass = null, string $type = null, string $id = null, array $data = null ): void { // ... }
从PHP 8.0开始,您可以使用命名参数以任何顺序指定函数参数。
示例1
// Delete all tokens related to Project model, where role is 'project-administrator' Token::deleteBy(modelClass: Project::class, ['role' => 'project-administrator']);
示例2
// Delete a single token by its unique ID Token::deleteBy(id: "9ad5a1f5-6207-4727-b1ee-e9eddbf752a1");
deleteTokens
函数在Eloquent模型类中的签名如下
function deleteTokens( string $type = null, string $id = null, array $data = null ): void { // ... }
示例1
// Delete all tokens related to the Project model instance, while targeting a specific token type $project->deleteTokens(type: "ACCESS_TOKEN");
示例2
// Delete a single token by its unique ID, also targeting the specific Project model instance $project->deleteTokens(id: "9ad5a1f5-6207-4727-b1ee-e9eddbf752a1");
强制删除所有令牌
要完全删除或黑名单所有已发行的令牌,可以使用forceDeleteAll方法。
此操作是不可逆的,应谨慎使用,因为它将永久删除系统中的所有令牌,使其无法用于任何进一步的操作或验证。
Token::forceDeleteAll();
由于其对令牌有效性和系统安全性的影响,应谨慎考虑在生产环境中使用。
高级令牌创建
指定令牌过期日期
在指定令牌的过期日期时,您可以选择使用Carbon实例或与strtotime()函数兼容的字符串。
// Use Carbon instance $expiresIn = now()->addDays(15); $token = $model->createToken("INVITE_TOKEN", $expiresIn)->getToken(); // Use `strtotime()` compatible string $token = $model->createToken("INVITE_TOKEN", "15 days")->getToken(); // Using Token facade $token = Token::create($model, "ACCESS_TOKEN", "15 minutes")->getToken();
包含额外数据
数据参数允许您将关联数组作为元数据与令牌一起包含。此功能非常适合添加与令牌功能相关的额外详细信息,包括角色、权限或任何其他类型的信息。
$data = ['role' => 'admin', 'projectId' => 123]; $token = $model->createToken('ACCESS_TOKEN', '+1 hour', $data)->getToken(); // Using Token facade $token = Token::create($model, "ACCESS_TOKEN", "15 minutes", $data)->getToken();
指定驱动程序
驱动程序参数允许您在创建令牌时显式指定要使用的令牌驱动程序。如果您已配置多个令牌驱动程序,并希望为某些令牌使用特定的驱动程序,可以指定驱动程序的名称。
如果没有指定驱动程序,它将自动回退到在配置文件中先前配置的默认驱动程序。
// Utilizes the `database` driver during token creation $token = $model->createToken('INVITE_TOKEN', $expiresIn, $data, 'database')->getToken(); // Using Token facade $token = Token::create($model, 'INVITE_TOKEN', $expiresIn, $data, 'database')->getToken();
高级令牌查询
您可以使用链式方法根据多个标准查找令牌
- whereModel(Model $model)
- whereModelClass(string $modelClass)
- whereType(string $type)
- whereData(array $data)
示例1
$model = Token::whereModelClass(Project::class) ->whereType("INVITE_TOKEN") ->findOrFail("eyJpdiI6Ik9FdFFqRmpxbXhh.....") ->getModel();
示例2
$model = Token::whereModelClass(Project::class) ->whereData(['role' => 'project-administrator']) ->whereType("INVITE_TOKEN") ->findOrFail("eyJpdiI6Ik9FdFFqRmpxbXhh.....") ->getModel();
示例3
$project = Project::find(12345); $isTokenFound = (bool) Token::whereModel($project) ->whereType("ACCESS_TOKEN") ->find("eyJpdiI6Ik9FdFFqRmpxbXhh.....");
理解TokenInstance
TokenInstance类是此令牌管理系统的重要组成部分。它包含特定令牌的所有相关信息,例如其标识符、关联模型、类型、创建时间、过期时间和附加数据。
可用方法
getDriver()
返回用于创建令牌实例的驱动程序名称。getId()
返回令牌的唯一标识符。getModel()
获取与令牌关联的Eloquent模型。getModelClass()
返回关联模型的类名。getModelId()
返回关联模型的ID/UUID。getType()
返回令牌的类型(例如,“ACCESS_TOKEN”)。getCreatedAt()
返回创建时间戳作为Carbon实例。getExpiresAt()
返回令牌的过期日期和时间(如果已设置过期时间)。getData()
返回与令牌关联的任何附加数据。getToken()
返回用于查找令牌的实际字符串值。
测试
为确保Laravel Eloquent Tokens的可靠性和功能性,您可以使用Composer命令运行测试
composer test
安全
如果您发现任何安全问题,请通过电子邮件boris@incollab.io联系我,或者如果您更愿意,您可以使用GitHub问题跟踪器报告问题。
许可
此软件包受MIT许可证许可。有关详细信息,请参阅许可证文件。