You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Silex JWT认证时如何记录请求并返回自定义无效令牌提示

解决Silex+JWT中请求日志记录与自定义错误提示的问题

我之前在使用Silex结合JWT做API认证时,也碰到过和你一模一样的问题——未携带令牌的请求直接返回默认错误,自己写的before中间件根本没触发,日志也打不上。后来才搞明白,核心问题出在中间件执行顺序和JWT认证事件的处理上,下面给你详细说解决方案:

一、为什么$app->before()没触发?

默认情况下,Lexik JWT认证的中间件优先级比你自定义的before中间件高(Silex中间件默认优先级是0,数字越大越先执行)。当请求没有携带令牌时,JWT中间件会在你的before之前就拦截请求,直接返回错误响应,导致你的日志代码根本没机会执行。

解决方法:提升日志中间件的优先级

把你的日志before中间件优先级设为一个较高的数值(比如100),确保它在JWT认证中间件之前执行:

use Symfony\Component\HttpFoundation\Request;

// 记录所有请求的日志,优先级100确保最先执行
$app->before(function (Request $request) use ($app) {
    $tokenExists = $request->headers->has('Authorization') && str_starts_with($request->headers->get('Authorization'), 'Bearer ');
    
    $app['logger']->info('API 请求记录', [
        '请求路径' => $request->getPathInfo(),
        '请求方法' => $request->getMethod(),
        '是否携带令牌' => $tokenExists ? '是' : '否',
        '客户端IP' => $request->getClientIp()
    ]);
}, 100);

二、自定义令牌无效/缺失的错误提示

JWT认证组件提供了专门的事件来处理认证失败的场景,我们只需要监听这些事件,替换默认的响应内容即可:

1. 监听「令牌缺失」事件

当请求完全没有携带JWT令牌时,会触发lexik_jwt_authentication.on_missing_token事件:

use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTMissingTokenEvent;
use Symfony\Component\HttpFoundation\JsonResponse;

$app['dispatcher']->addListener('lexik_jwt_authentication.on_missing_token', function (JWTMissingTokenEvent $event) {
    $customResponse = new JsonResponse([
        'code' => 401,
        'message' => '请先登录获取有效的身份令牌,再访问此接口'
    ], 401);
    
    $event->setResponse($customResponse);
});

2. 监听「令牌无效/认证失败」事件

当令牌过期、签名错误等无效情况时,会触发lexik_jwt_authentication.on_authentication_failure事件:

use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTAuthenticationFailureEvent;

$app['dispatcher']->addListener('lexik_jwt_authentication.on_authentication_failure', function (JWTAuthenticationFailureEvent $event) {
    $customResponse = new JsonResponse([
        'code' => 401,
        'message' => '身份令牌无效,请重新登录'
    ], 401);
    
    $event->setResponse($customResponse);
});

三、完整的整合示例

把上面的代码和你原有的接口代码整合起来,大概是这样:

use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTMissingTokenEvent;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTAuthenticationFailureEvent;
use Symfony\Component\HttpFoundation\JsonResponse;

$app = new Application();

// 1. 配置日志服务(假设你已经配置好了monolog等日志组件)
$app['monolog.logfile'] = __DIR__.'/logs/api.log';
$app->register(new Silex\Provider\MonologServiceProvider(), [
    'monolog.name' => 'api',
    'monolog.logfile' => $app['monolog.logfile'],
]);

// 2. 注册JWT认证服务(你的原有配置)
// $app->register(new Lexik\Bundle\JWTAuthenticationBundle\Provider\JWTServiceProvider(), [
//     'lexik_jwt_authentication.secret_key' => 'your_secret_key',
//     // 其他JWT配置...
// ]);

// 3. 高优先级的请求日志中间件
$app->before(function (Request $request) use ($app) {
    $tokenExists = $request->headers->has('Authorization') && str_starts_with($request->headers->get('Authorization'), 'Bearer ');
    
    $app['logger']->info('API 请求记录', [
        '请求路径' => $request->getPathInfo(),
        '请求方法' => $request->getMethod(),
        '是否携带令牌' => $tokenExists ? '是' : '否',
        '客户端IP' => $request->getClientIp()
    ]);
}, 100);

// 4. 自定义令牌缺失响应
$app['dispatcher']->addListener('lexik_jwt_authentication.on_missing_token', function (JWTMissingTokenEvent $event) {
    $customResponse = new JsonResponse([
        'code' => 401,
        'message' => '请先登录获取有效的身份令牌,再访问此接口'
    ], 401);
    
    $event->setResponse($customResponse);
});

// 5. 自定义令牌无效响应
$app['dispatcher']->addListener('lexik_jwt_authentication.on_authentication_failure', function (JWTAuthenticationFailureEvent $event) {
    $customResponse = new JsonResponse([
        'code' => 401,
        'message' => '身份令牌无效,请重新登录'
    ], 401);
    
    $event->setResponse($customResponse);
});

// 6. 你的受保护接口
$app->get('/api/protected_resource', function() use ($app){ 
    // 接口逻辑
    return new JsonResponse(['data' => '这是受保护的资源']);
})->before($app['lexik_jwt_authentication.authentication_handler']);

$app->run();

这样调整后,不管请求是否携带令牌,都会先触发日志中间件记录请求;同时令牌缺失或无效时,会返回你自定义的提示信息,而不是默认的错误内容。

内容的提问来源于stack exchange,提问作者Divesh Oswal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:03:11