liliuwei/think-api-auth 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

liliuwei/think-api-auth

Composer 安装命令:

composer require liliuwei/think-api-auth

包简介

适用于ThinkPHP 6.0+的API鉴权扩展,支持JWT双令牌与签名认证,多守卫隔离

README 文档

README

适用于 ThinkPHP 6.0+ 的 API 鉴权扩展,提供 JWT 双令牌与签名认证两种模式,支持多守卫隔离。

特性

  • JWT 双令牌 — Access Token + Refresh Token,符合行业标准
  • 多守卫 — 多端独立鉴权(api / admin / open 等),互不干扰
  • 令牌黑名单 — 刷新后旧令牌自动失效,防止泄露滥用
  • 强制下线 — 支持 token_version 机制,一键踢人
  • 签名认证 — HMAC-SHA256 + nonce 防重放,适合服务端对接
  • 事件系统 — Login / Logout / TokenRefreshed,方便审计
  • 用户提供者 — 可注入回调验证用户状态
  • 零外部依赖 — 自研 JWT 实现,不依赖第三方 JWT 库

安装

composer require liliuwei/think-api-auth

首次安装后会在 config/auth.php 生成一份默认配置,之后修改此文件即可, 扩展会优先读取项目中的配置。

配置

// config/auth.php
return [
    // 默认守卫
    'default' => 'api',

    // 守卫定义
    'guards' => [
        'api' => [
            'type'                  => 'jwt',
            'secret'                => 'your-api-secret-key',
            'algo'                  => 'sha256',        // sha256 / sha384 / sha512
            'iss'                   => 'api',           // 签发者
            'aud'                   => 'api',           // 受众
            'leeway'                => 0,               // 时间偏差容忍(秒)
            'access_ttl'            => 7200,            // Access Token 有效期(秒)
            'refresh_ttl'           => 604800,          // Refresh Token 有效期(秒)
            'blacklist_enabled'     => true,            // 启用黑名单
            'blacklist_cache_prefix'=> 'auth_blacklist_',
            'user_provider'         => null,            // 用户验证回调
        ],
        'admin' => [
            'type'       => 'jwt',
            'secret'     => 'admin-secret-key',
            'access_ttl' => 3600,
            'refresh_ttl'=> 86400,
        ],
        'open' => [
            'type'       => 'signature',
            'app_secret' => 'open-api-secret',
        ],
    ],

    // 签名认证参数
    'signature' => [
        'timeout'     => 60,
        'algo'        => 'sha256',
        'nonce_cache' => true,
        'nonce_ttl'   => 300,
    ],

    // 请求头字段名
    'header_keys' => [
        'app_key'   => 'X-App-Key',
        'timestamp' => 'X-Timestamp',
        'nonce'     => 'X-Nonce',
        'sign'      => 'X-Sign',
    ],

    // 白名单(不鉴权的路由)
    'white_list' => [
        'api/login',
        'api/register',
        'api/public/*',
    ],

    // 自定义响应状态码
    'response_code' => [
        'unauthorized'  => 401,
        'token_expired' => 401,
    ],
];

快速开始

1. 登录签发令牌

use liliuwei\think\auth\ApiAuth;

class AuthController
{
    public function login()
    {
        // 验证账号密码...
        $user = User::where('username', input('username'))->find();
        if (!$user || !password_verify(input('password'), $user->password)) {
            return json(['code' => 1, 'msg' => '账号或密码错误']);
        }

        $auth = app(ApiAuth::class);
        $result = $auth->login([
            'sub'      => $user->id,
            'username' => $user->username,
            'role'     => $user->role,
        ]);

        return json(['code' => 0, 'msg' => '登录成功', 'data' => $result]);
    }
}

返回数据:

{
    "code": 0,
    "msg": "登录成功",
    "data": {
        "access_token": "eyJhbGciOiJIUzI1NiIs...",
        "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
        "expires_in": 7200,
        "token_type": "Bearer"
    }
}

2. 路由鉴权

use liliuwei\think\auth\middleware\Auth as AuthMiddleware;

// 默认守卫 api
Route::group('api', function () {
    Route::get('user/info', 'User/info');
    Route::post('order/create', 'Order/create');
})->middleware(AuthMiddleware::class);

// 指定 admin 守卫
Route::group('admin', function () {
    Route::get('dashboard', 'Admin/dashboard');
})->middleware(new AuthMiddleware('admin'));

3. 客户端请求

GET /api/user/info
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

4. 控制器获取用户

class User
{
    public function info(Request $request)
    {
        $user = $request->auth_user;
        // {
        //     "sub": 1,
        //     "username": "admin",
        //     "role": "admin",
        //     "iss": "api",
        //     "aud": "api",
        //     "iat": 1718280000,
        //     "exp": 1718287200,
        //     "jti": "a1b2c3..."
        // }

        return json(['code' => 0, 'data' => $user]);
    }
}

5. 刷新令牌

class AuthController
{
    public function refresh()
    {
        $auth = app(ApiAuth::class);
        $result = $auth->refresh(input('refresh_token'));

        return json(['code' => 0, 'data' => $result]);
    }
}

6. 登出

class AuthController
{
    public function logout()
    {
        app(ApiAuth::class)->logout();
        return json(['code' => 0, 'msg' => '已登出']);
    }
}

进阶用法

用户提供者(验证用户状态)

在守卫配置中注入 user_provider 回调,可以在每次请求时验证用户是否合法:

'user_provider' => function ($payload) {
    $user = \app\model\User::find($payload['sub']);
    if (!$user || $user->status === 0) {
        return null;
    }
    return $user;
},

强制下线(Token 版本)

让用户模型实现 Authenticatable 接口:

use liliuwei\think\auth\contract\Authenticatable;

class User extends Model implements Authenticatable
{
    public function getAuthIdentifier()
    {
        return $this->id;
    }

    public function getTokenVersion()
    {
        return $this->token_version;
    }

    public function getAuthMeta(): array
    {
        return ['username' => $this->username, 'role' => $this->role];
    }
}

登录时带上版本号:

$auth->login([
    'sub'           => $user->id,
    'token_version' => $user->token_version,
]);

踢人下线时只需递增 token_version,所有旧令牌立即失效。

多守卫切换

$auth = app(ApiAuth::class);

// 使用默认守卫
$auth->login(['sub' => 1]);

// 使用 admin 守卫
$auth->guard('admin')->login(['sub' => 1]);

// 或直接用参数
$auth->login(['sub' => 1], 'admin');
$auth->refresh($token, 'admin');
$auth->logout('admin');

门面调用

use liliuwei\think\auth\Facade as Auth;

Auth::login(['sub' => $user->id]);
Auth::refresh($refreshToken);
$user = Auth::user();
$uid  = Auth::id();
Auth::check();  // 是否已认证
Auth::guest();  // 是否游客

签名认证模式

// 服务端生成签名参数
$auth = app(ApiAuth::class);
$params = $auth->guard('open')->generateSignatureParams('app_key_001', [
    'page' => 1,
    'size' => 10,
]);

// 返回
// {
//     "app_key": "app_key_001",
//     "timestamp": 1718280000,
//     "nonce": "a1b2c3d4e5f6...",
//     "sign": "abc123def456..."
// }

客户端携带以上参数请求即可。

事件监听

// app/event.php
return [
    \liliuwei\think\auth\event\Login::class => [\app\listener\AuthLog::class],
    \liliuwei\think\auth\event\Logout::class => [\app\listener\AuthLog::class],
    \liliuwei\think\auth\event\TokenRefreshed::class => [\app\listener\AuthLog::class],
];
// app/listener/AuthLog.php
class AuthLog
{
    public function handle($event)
    {
        $guard = $event->guard;
        $user  = $event->user;
        // 写入审计日志
    }
}

异常处理

所有鉴权异常均继承 liliuwei\think\exception\AuthException,可在全局异常处理中统一捕获:

// app/ExceptionHandle.php
use liliuwei\think\exception\TokenExpiredException;
use liliuwei\think\exception\InvalidTokenException;

public function render($request, \Throwable $e)
{
    if ($e instanceof TokenExpiredException) {
        return json(['code' => 401, 'msg' => '令牌已过期,请刷新']);
    }
    if ($e instanceof InvalidTokenException) {
        return json(['code' => 401, 'msg' => $e->getMessage()]);
    }
    return parent::render($request, $e);
}

目录结构

src/
├── config/api_auth.php
├── contract/Authenticatable.php
├── jwt/
│   ├── Jwt.php
│   └── Blacklist.php
├── guard/
│   ├── Guard.php
│   ├── JwtGuard.php
│   └── SignatureGuard.php
├── event/
│   ├── Login.php
│   ├── Logout.php
│   └── TokenRefreshed.php
├── exception/
│   ├── AuthException.php
│   ├── UnauthorizedException.php
│   ├── ForbiddenException.php
│   ├── InvalidTokenException.php
│   ├── TokenExpiredException.php
│   ├── RefreshTokenException.php
│   └── SignatureException.php
├── middleware/Auth.php
├── ApiAuth.php
├── Facade.php
└── Service.php

License

Apache-2.0

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Apache-2.0
  • 更新时间: 2026-06-13