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

CodeIgniter无法捕获JWT过期异常,跳转登录页失败

问题:CodeIgniter中JWT过期异常无法捕获,无法跳转登录页

我需要每次刷新页面时校验JWT Token,将其作为过滤器使用。Token不存在或被清除时能正常跳转至登录页,但Token过期时,CodeIgniter会直接抛出JWT过期异常,无法捕获异常并携带Flash数据跳转登录页。

尝试在调用校验函数时嵌套try-catch块,不仅没捕获到错误,反而出现Undefined property: CodeIgniter\HTTP\RedirectResponse::$email错误。


相关代码

jwt_helper.php

function validateJWT($token)
{
    $session = \Config\Services::session();
    $model = new UserModel();
    $key = getenv('JWT_SECRET_KEY');
    try {
        $decoded_token = JWT::decode($token, new Key($key, 'HS256'));
        return $decoded_token;
    } catch (Exception $e) {
        setcookie('COOKIE-SESSION', null);
        $session->setFlashdata('message', '<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-300 dark:bg-gray-800 dark:text-red-400" role="alert">
                <span class="font-medium">Token Invalid</span>, Please login again
              </div>');
        // echo $e->getMessage();
        return redirect()->to('/auth');
    }
}

DashboardController.php

public function show()
{
    $session = \Config\Services::session();
    $token = $_COOKIE['COOKIE-SESSION'];
    $model = new UserModel();
    helper('jwt');
    try {
        $decoded_token = validateJWT($token);
        $result = $model->show($decoded_token->email);
    } catch (Exception $e) {
        $session->setFlashdata('message', '<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-300 dark:bg-gray-800 dark:text-red-400" role="alert">
        <span class="font-medium">Session Expired</span>, Please login again
        </div>');
        return redirect()->to('/auth');
    }
    if (!$result) {
        $data['title'] = 'Login';
        $session->setFlashdata('message', 'Session expired, Please login again');
        return view('login', $data);
    } else {
        $data = [
            'title' => 'Dashboard',
            'email' => $result['email'],
            'name' => $result['name'],
            'image' => $result['image'],
            'date_created' => $result['date_created']
        ];
        $session->set('title', $data['title']);
        return view('dashboard', $data);
    }
}

UserModel.php

public function show($email)
{
    $session = \Config\Services::session();
    $model = new UserModel();
    $builder = $this->table('users');
    $data = $builder->where('email', $email)->first();
    if (!$data) {
        return false;
    } else {
        $data2 = [
            'email' => $data['email'],
            'name' => $data['name'],
            'image' => $data['image'],
            'date_created' => $data['date_created']
        ];
        return $data2;
    }
}

解决方案

1. 捕获JWT具体异常类

JWT库抛出的不是通用Exception,而是专属异常(如ExpiredException、SignatureInvalidException),需针对性捕获:

修改jwt_helper.php:

use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Exception;

function validateJWT($token)
{
    $session = \Config\Services::session();
    $key = getenv('JWT_SECRET_KEY');
    try {
        $decoded_token = JWT::decode($token, new Key($key, 'HS256'));
        return $decoded_token;
    } catch (ExpiredException $e) {
        // 正确清除Cookie(设置过期时间为过去)
        setcookie('COOKIE-SESSION', null, -1, '/');
        $session->setFlashdata('message', '<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-300 dark:bg-gray-800 dark:text-red-400" role="alert">
                <span class="font-medium">Session Expired</span>, Please login again
              </div>');
        return redirect()->to('/auth');
    } catch (SignatureInvalidException|BeforeValidException|Exception $e) {
        setcookie('COOKIE-SESSION', null, -1, '/');
        $session->setFlashdata('message', '<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-300 dark:bg-gray-800 dark:text-red-400" role="alert">
                <span class="font-medium">Token Invalid</span>, Please login again
              </div>');
        return redirect()->to('/auth');
    }
}

2. 处理Helper返回的跳转响应

当Helper返回RedirectResponse时,控制器不能将其当作解码后的Token使用,需先判断类型:

修改DashboardController.php:

public function show()
{
    $session = \Config\Services::session();
    // 先检查Cookie是否存在,避免Undefined index错误
    if (!isset($_COOKIE['COOKIE-SESSION'])) {
        $session->setFlashdata('message', '<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-300 dark:bg-gray-800 dark:text-red-400" role="alert">
        <span class="font-medium">Session Expired</span>, Please login again
        </div>');
        return redirect()->to('/auth');
    }
    $token = $_COOKIE['COOKIE-SESSION'];
    $model = new UserModel();
    helper('jwt');
    
    $decoded_token = validateJWT($token);
    // 判断是否为跳转响应,是则直接返回
    if ($decoded_token instanceof \CodeIgniter\HTTP\RedirectResponse) {
        return $decoded_token;
    }
    
    $result = $model->show($decoded_token->email);
    
    if (!$result) {
        $data['title'] = 'Login';
        $session->setFlashdata('message', 'Session expired, Please login again');
        return view('login', $data);
    } else {
        $data = [
            'title' => 'Dashboard',
            'email' => $result['email'],
            'name' => $result['name'],
            'image' => $result['image'],
            'date_created' => $result['date_created']
        ];
        $session->set('title', $data['title']);
        return view('dashboard', $data);
    }
}

3. 修复UserModel冗余代码

UserModel内无需重新实例化自身,直接使用$this即可:

public function show($email)
{
    $builder = $this->table('users');
    $data = $builder->where('email', $email)->first();
    if (!$data) {
        return false;
    } else {
        return [
            'email' => $data['email'],
            'name' => $data['name'],
            'image' => $data['image'],
            'date_created' => $data['date_created']
        ];
    }
}

4. 可选:使用框架内置Cookie服务

替代原生setcookie,更符合CodeIgniter规范:

$response = \Config\Services::response();
$response->deleteCookie('COOKIE-SESSION');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:05:28