当验证从PHP生成的jwt令牌时,jjwt引发签名错误

时间:2019-07-31 18:53:23

标签: java php jwt jjwt

我需要在使用Java的CAS构建的SSO中添加PHP应用程序。 在对用户进行身份验证之后,SSO将凭据发送到PHP App,并使用以下代码构建令牌:

public function getToken(Signer $signer = null, Key $key = null)
    {
        $signer = $signer ?: $this->signer;
        $key = $key ?: $this->key;

        if ($signer instanceof Signer) {
            $signer->modifyHeader($this->headers);
        }

        $payload = [
            $this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)),
            $this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims))
        ];

        $signature = $this->createSignature($payload, $signer, $key);

        if ($signature !== null) {
            $payload[] = $this->encoder->base64UrlEncode($signature);
        }

        return new Token($this->headers, $this->claims, $signature , $payload);
    }

    private function createSignature(array $payload, Signer $signer = null, Key $key = null)
    {
        if ($signer === null || $key === null) {
            return null;
        }
        return $signer->sign(implode('.', $payload), $key);
    }

因此,我尝试使用Java来验证生成的令牌,如下所示:

 public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
            return true;
        } catch (SignatureException e) {
            log.info("Invalid JWT signature.");
            log.trace("Invalid JWT signature trace: {}", e);
            e.printStackTrace();
        }
        ....
    }

要验证签名,jjwt会拆分令牌的3个部分,并尝试使用令牌标头中提供的算法对2个“第一”部分进行签名。创建令牌时,此步骤与创建令牌的签名相同。从理论上讲,使用相同的算法,在创建和验证两个步骤中都使用工资和秘密,签名应该相同。 但这不会发生。 引发以下异常:

  

io.jsonwebtoken.SignatureException:JWT签名与本地计算的签名不匹配。 JWT的有效性不能断言,也不应该被信任。

1 个答案:

答案 0 :(得分:0)

我会回答我自己的问题。 jjwt需要一个base64加密的秘密。但是在我的Java代码中,我没有在解析器中设置密码之前对其进行编码。

这是jjwt验证令牌签名的方式:

    public boolean isValid(String jwtWithoutSignature, String base64UrlEncodedSignature) {

        byte[] data = jwtWithoutSignature.getBytes(US_ASCII);

        byte[] signature = TextCodec.BASE64URL.decode(base64UrlEncodedSignature);

        return this.signatureValidator.isValid(data, signature);
    }

我在Java代码中所做的更改:

    secretKey = TextCodec.BASE64URL.encode(secret);
    Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken)