Codeigniter 4 Shield:如何签发访问令牌并解决空对象调用错误
解决CodeIgniter 4 Shield生成访问令牌时的"Call to a member function generateAccessToken() on null"错误
错误原因
auth()->user()返回null,说明访问/access/token路由时当前用户未通过认证。Shield的auth()->user()仅在用户已登录(通过Session或Token认证)时才会返回有效的用户实例,直接浏览器访问该路由时没有携带登录会话,因此触发错误。
正确实现方式
1. 给路由添加认证保护
首先要确保只有已登录用户才能访问该路由,使用Shield内置的auth过滤器,同时处理token_name的默认值、规范响应格式:
$routes->get('/access/token', static function() { $tokenName = service('request')->getVar('token_name') ?? 'default-token'; $token = auth()->user()->generateAccessToken($tokenName); return service('response')->setJSON(['token' => $token->raw_token]); })->filter('auth');
如果需要更明确的错误提示,也可以手动校验认证状态:
$routes->get('/access/token', static function() { if (!auth()->check()) { return service('response') ->setJSON(['error' => '未认证用户无法生成访问令牌']) ->setStatusCode(401); } $tokenName = service('request')->getVar('token_name') ?? 'default-token'; $token = auth()->user()->generateAccessToken($tokenName); return service('response')->setJSON(['token' => $token->raw_token]); })->filter('auth');
2. 验证用户模型的AccessToken特性
检查你的App\Models\User模型是否启用了Shield的HasAccessTokens trait,这是生成令牌的必要前提:
<?php namespace App\Models; use CodeIgniter\Shield\Models\User as ShieldUser; use CodeIgniter\Shield\Models\Traits\HasAccessTokens; class User extends ShieldUser { use HasAccessTokens; // 其他模型代码 }
3. 正确访问路由的方式
- 先通过登录页面/接口完成登录,确保会话有效
- 访问路由时可携带自定义令牌名称:
https://example.com/access/token?token_name=my-app-token,不传则使用代码中设置的default-token作为名称
额外注意
- 避免直接用
json_encode返回响应,CodeIgniter的setJSON()方法会自动设置正确的Content-Type响应头,更符合API规范 - 如果需要通过API Token而非Session认证访问该路由,需在请求头中携带
Authorization: Bearer {已有的有效令牌},此时auth()->user()也能正确返回用户实例
内容的提问来源于stack exchange,提问作者luis
相关产品推荐
相关产品推荐

