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

为何我的JWT仅能通过私钥验证,无法通过公钥验证?

JWT验证异常:仅能通过私钥验证,公钥验证失败

我遇到一个奇怪的问题:可以正常生成JWT并发送给API客户端(当前用Insomnia测试),但在服务器端,该令牌仅能通过私钥验证,无法通过公钥验证。私钥验证不仅不安全,理论上也不应该可行!

背景

服务器基于PHP开发,使用Lcobucci的JWT库。

密钥生成命令

openssl genrsa -out ./keys/private.key 2048
openssl rsa -in ./keys/private.key -pubout -out ./keys/public.key

相关代码

use Lcobucci\JWT\Token\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Encoding\{ChainedFormatter,JoseEncoder};
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\Validator as JWTValidator;
use Lcobucci\JWT\Validation\Constraint\SignedWith;

$this->private_key = InMemory::file($private_key_path);
$this->public_key = InMemory::file($public_key_path);

// 日志输出显示两个密钥内容均正常

$token_builder = new Builder(new JoseEncoder(), ChainedFormatter::default());
$algorithm = new Sha256();
$signing_key = $this->private_key;
$now = new \DateTimeImmutable();
$exp = $now->modify('+1 hour');

$access_token = $token_builder
    ->issuedBy('my-system')
    ->permittedFor('my-frontend-system')
    ->identifiedBy(uniqid())
    ->issuedAt($now)
    ->canOnlyBeUsedAfter($now)
    ->expiresAt($exp)
    ->withClaim('user_id', $authentication['user_id'])
    ->withClaim('user_roles', $roles)
    ->getToken($algorithm, $signing_key);
$validator = new JWTValidator();
if (!$validator->validate($access_token, new SignedWith($algorithm, $this->public_key))) {
  throw new AuthenticationException("The generated token was invalid");
}

如上代码所示,我简化了逻辑,尝试在生成令牌后立即验证,但仍会抛出异常!将验证器中的$this->public_key改为$this->private_key则不会报错。

通常我在整理问题时能自行发现根源,但这次毫无头绪,恳请帮忙排查问题!

补充信息

查看令牌头部后发现,算法为HS256,而非预期的RS256:

{
  "typ": "JWT",
  "alg": "HS256" // *问题所在,应该是RS256!*
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:10:44