【发布时间】:2020-01-23 23:54:22
【问题描述】:
我是新手,我正在尽力创建自己的 JWT 类。我认为我做的一切都是正确的,但是当我尝试将我的令牌粘贴到 jwt.io 中时,它一直说签名无效。我不禁觉得我要么错过了什么愚蠢的东西,要么有什么不对劲。
我的代码如下:
class Jwt
{
protected $header;
protected $payload;
protected $signature;
protected $secret;
protected $alg;
protected $jwt;
function __construct($header, $payload, $secret)
{
$this->SetHeader($header);
$this->alg = $header['alg'];
$this->SetPayload($payload);
$this->secret = $secret;
$this->SetSignature();
}
public function SetHeader($header){
$this->header = str_replace(["+", "/", "="],
['-', '_',""],
base64_encode(json_encode($header)));
}
public function SetPayload($payload)
{
$this->payload =
str_replace(["+", "/", "="],
['-', '_',""],
base64_encode(json_encode($payload)));
}
public function SetSignature()
{
$data = $this->header.".".$this->payload;
$this->alg = str_replace('HS', 'sha', $this->alg);
$hashedData = hash_hmac($this->alg, $data , $this->secret, true);
$this->signature = str_replace(
["+", "/", "="], ['-', '_', ""], base64_encode($hashedData)
);
}
public function SetJwt()
{
$this->jwt = $this->header.'.'.$this->payload.'.'.$this->signature;
}
public function GetJwt()
{
return $this->jwt;
}
在我的 Index.php 中:
use root\lib\Jwt;
$myFavorites =
['element' => 'Sun', 'animal' => 'Leopard','color'=>'Orange'];
$secret = bin2hex(random_bytes(32));
$jwt = new Jwt
(['alg' => 'HS256', 'typ' => 'JWT'], $myFavorites, $secret)
$jwt->SetJwt();
var_dump($jwt->GetJwt());
一切正常,调试器显示正确的输出,但不知何故它只是说无效签名。
如果我更改 jwt.io 网站上的算法,它会起作用。所以我猜它与签名或算法有关
我正在从 var_dump 的屏幕输出中复制它,这可能是原因吗?
新令牌是:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbGVtZW50IjoiU3VuIiwiYW5pbWFsIjoiTGVvcGFyZCIsImNvbG91ciI6Im9yYW5nZSJ9.LF-4HNxgzhqYaIQKTImwO8A4SHIZfVYzG
我什至尝试更改标头 HS256 或 HS384 中的算法,然后在函数内部对更改进行硬编码,没有任何区别
任何建议将不胜感激
【问题讨论】:
-
试试base64UrlEncoding:
function base64url_encode($data) { return rtrim( strtr(base64_encode($data), '+/', '-_'), '=');} -
我试了一下,结果一样,很奇怪
-
一旦我把它放在调试器中,然后在那里更改算法,然后回到它工作的相同算法,但 JWT 会为它创建自己的新签名
-
token 看起来基本没问题,只有 alg 标头错误。您是否也将秘密粘贴到 jwt.io 调试器的
verify signature下的秘密字段中? -
现在我认为它有效:),希望它不太好,我打算用不同的号码再试一次。你认为秘密应该用随机数生成吗?