我需要在使用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的有效性不能断言,也不应该被信任。
答案 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)