Firebase JWT decode报错:参数$headers无法按引用传递
Firebase JWT解码时“Argument #3 cannot be passed by reference”错误解决
问题场景
使用PHP版Firebase JWT库实现API认证,登录生成JWT后,调用其他接口解码Token时触发致命错误:
Fatal error: Uncaught Error: Firebase\JWT\JWT::decode(): Argument #3 ($headers) cannot be passed by reference in /home/kuba/projects/jcubic/terminal/jwt/service.php:45
尝试将['HS512']改为array('HS512')后报错依旧,代码用于jQuery Terminal的JSON-RPC接口,Auth类作为Service对象的包装,登录获取Token后存入localStorage,作为其他方法的首个参数传递。
错误原因
Firebase JWT的decode方法第三个参数($headers)是按引用传递的,PHP语法规则不允许直接将字面量数组(如['HS512'])传递给按引用的参数,必须先将数组赋值给一个变量,再传递该变量。
解决方案
1. 修正valid_token方法
将允许的算法数组先赋值给变量,再传递给JWT::decode,同时修正Token生效时间的判断逻辑:
private function valid_token($jwt) { global $env; // 先将算法数组赋值给变量 $allowed_algs = ['HS512']; $token = JWT::decode($jwt, $env['secret'], $allowed_algs); $now = new DateTimeImmutable(); return $token->iss == $env['domain'] && $token->nbf <= $now->getTimestamp() && // 修正nbf判断逻辑:当前时间不早于Token生效时间 $token->exp > $now->getTimestamp(); }
2. 修复__call方法未定义变量问题
原代码中$methods变量未定义,需先声明允许调用的Service方法列表:
public function __call($method, $params) { $jwt = array_shift($params); if (!$this->valid_token($jwt)) { throw new Exception("Invalid Token"); } // 定义允许调用的Service方法列表,替换为实际业务方法名 $methods = ['getUserData', 'updateProfile']; if (!in_array($method, $methods)) { throw new Exception("Invalid method $method"); } return call_user_func_array(array($this->service, $method), $params); }
修正后的完整代码
$env = parse_ini_file('.env'); class Auth { private $service; public function __construct($service) { $this->service = $service; } public function login($user, $password) { global $env; if ($user != $env['user'] || $password != $env['password']) { return null; } $date = new DateTimeImmutable(); $expire_at = $date->modify('+6 minutes')->getTimestamp(); $payload = [ 'iat' => $date->getTimestamp(), 'iss' => $env['domain'], 'nbf' => $date->getTimestamp(), 'exp' => $expire_at, 'userName' => $user, ]; return JWT::encode( $payload, $env['secret'], 'HS512' ); } private function valid_token($jwt) { global $env; $allowed_algs = ['HS512']; $token = JWT::decode($jwt, $env['secret'], $allowed_algs); $now = new DateTimeImmutable(); return $token->iss == $env['domain'] && $token->nbf <= $now->getTimestamp() && $token->exp > $now->getTimestamp(); } public function __call($method, $params) { $jwt = array_shift($params); if (!$this->valid_token($jwt)) { throw new Exception("Invalid Token"); } // 替换为实际需要开放的Service方法名 $methods = ['getUserData', 'updateProfile']; if (!in_array($method, $methods)) { throw new Exception("Invalid method $method"); } return call_user_func_array(array($this->service, $method), $params); } }
内容的提问来源于stack exchange,提问作者jcubic
相关产品推荐
相关产品推荐

