如何在CodeIgniter中将Token从一个控制器传递到另一个控制器?
在CodeIgniter中从其他控制器获取并验证JWT Token
一、前端传递Token的核心方式
用户登录拿到Token后,前端需要在后续所有需要鉴权的请求中,将Token放在HTTP请求头的Authorization字段里,格式固定为:
Authorization: Bearer <你的Token字符串>
二、目标控制器中获取并验证Token的实现
以你提到的/me接口为例,创建MeController来获取当前用户信息,示例代码如下:
<?php namespace App\Controllers; use CodeIgniter\RESTful\ResourceController; use CodeIgniter\API\ResponseTrait; use Firebase\JWT\JWT; use Firebase\JWT\Key; use App\Models\UserModel; class Me extends ResourceController { use ResponseTrait; public function index() { // 1. 从请求头提取Authorization字段 $authHeader = $this->request->getHeaderLine('Authorization'); // 2. 校验Token是否存在、格式是否合规 if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) { return $this->failUnauthorized('Token未提供或格式错误'); } // 3. 剥离前缀,拿到纯Token字符串 $token = substr($authHeader, 7); try { // 4. 验证并解析Token $key = getenv('TOKEN_SECRET'); $payload = JWT::decode($token, new Key($key, 'HS256')); // 5. 根据Token中的用户ID获取用户信息(可选操作) $userModel = new UserModel(); $user = $userModel->find($payload->uid); if (!$user) { return $this->failNotFound('用户不存在'); } // 移除敏感字段后返回用户信息 unset($user['password']); return $this->respond($user); } catch (\Firebase\JWT\ExpiredException $e) { return $this->failUnauthorized('Token已过期'); } catch (\Exception $e) { return $this->failUnauthorized('Token无效'); } } }
三、封装公共验证逻辑(推荐)
为了避免重复写Token校验代码,可以把逻辑封装到BaseController中,让所有需要鉴权的控制器继承它:
<?php namespace App\Controllers; use CodeIgniter\Controller; use Firebase\JWT\JWT; use Firebase\JWT\Key; class BaseController extends Controller { protected $user; public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger) { parent::initController($request, $response, $logger); // 登录接口跳过Token验证,其余接口自动校验 if ($this->request->uri->getPath() !== 'login') { $this->validateToken(); } } protected function validateToken() { $authHeader = $this->request->getHeaderLine('Authorization'); if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) { $this->response->setStatusCode(401)->setJSON(['error' => 'Token未提供或格式错误'])->send(); exit; } $token = substr($authHeader, 7); $key = getenv('TOKEN_SECRET'); try { $payload = JWT::decode($token, new Key($key, 'HS256')); // 提前获取用户信息,供后续控制器直接使用 $userModel = new \App\Models\UserModel(); $this->user = $userModel->find($payload->uid); if (!$this->user) { $this->response->setStatusCode(404)->setJSON(['error' => '用户不存在'])->send(); exit; } } catch (\Firebase\JWT\ExpiredException $e) { $this->response->setStatusCode(401)->setJSON(['error' => 'Token已过期'])->send(); exit; } catch (\Exception $e) { $this->response->setStatusCode(401)->setJSON(['error' => 'Token无效'])->send(); exit; } } }
之后你的MeController可以简化为:
<?php namespace App\Controllers; use CodeIgniter\RESTful\ResourceController; use CodeIgniter\API\ResponseTrait; class Me extends BaseController { use ResponseTrait; public function index() { // 直接使用父类中已验证通过的用户信息 unset($this->user['password']); return $this->respond($this->user); } }
关键优化提示
你当前Login控制器中的iat和nbf字段是固定值,建议改成动态时间戳并添加过期时间:
$payload = [ 'iat' => time(), // Token生成时间 'nbf' => time(), // Token生效时间(立即生效) 'exp' => time() + 3600, // Token过期时间(1小时后) 'uid' => $user['id'], 'email' => $user['email'], ];
添加exp字段后,JWT库会自动校验Token是否过期,无需手动判断。
内容的提问来源于stack exchange,提问作者Tommi Andrean
相关产品推荐
相关产品推荐

