JWT decode() 必须是数组错误类型

Posted

技术标签:

【中文标题】JWT decode() 必须是数组错误类型【英文标题】:JWT decode() must be of the type array error 【发布时间】:2019-08-16 13:27:15 【问题描述】:

这里我有一些用于登录的纤细 php 代码和一个检查它是否解码存储在标头中的 JWT 的函数。

$app->post('/login', function ($request, $response) 

$input = $request->getParsedBody();
$settings = $this->get('settings'); // get settings array.
$sql = "SELECT id, password FROM users WHERE id= :id";
$sth = $this->db->prepare($sql);
$sth->bindParam("id", $input['id']);
$sth->execute();
$user = $sth->fetchObject();

// verify user id 
if(!$user) 
    return $this->response->withJson(['error' => true, 'message' => 'NO ID '], 404)->withHeader('Content-type', 'application/json;charset=utf-8', 404);

// Compare the input password and the password from database for a validation
if (strcmp($input['password'],$user->password)) 
    return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.'], 404)->withHeader('Content-type', 'application/json;charset=utf-8', 404);  


$payload = array(
    "iat" => time(),
    "exp" => time() + 36000,
    // "id" => $input['id']
    "context" => [
        "user" => [
            "id" => $input['id']
        ]
    ]
);

try 
    $token = JWT::encode($payload, $settings['jwt']['secret'],"HS256"); // $token store the token of the user
 catch (Exception $e) 
    echo json_encode($e);



return $this->response->withJson($payload,200)
                      ->withHeader('Content-type', 'application/json;charset=utf-8', 200)
                      ->withAddedHeader('Authorization', $token);
);


$app->get('/get', function ($request, $response) 

$jwt = $request->getHeader("Authorization"); 
$settings = $this->get('settings'); 

$token = JWT::decode($jwt, $settings['jwt']['secret'], "HS256"); // $token store the token of the user

if ($token) 
    return $this->response->withJson($token, 200)
    ->withHeader('Content-type', 'application/json;charset=utf-8', 200);


return $this->response->withJson($token,401)
                      ->withHeader('Content-type', 'application/json;charset=utf-8', 401);

);

但是当我尝试运行http://localhost:8080/get 时,它会返回一个错误

传递给 Firebase\JWT\JWT::decode() 的参数 3 必须是数组类型。

为什么会发生,我该如何解决?

【问题讨论】:

警告! strcmp($input['password'],$user->password) 表明您没有正确散列密码。在处理密码时,您应该始终使用password_hash 和password_verify()。 从不将它们存储为纯文本或使用任何自建的散列算法。 是的,我知道,我不是为了生产。稍后将实施安全性。谢谢 print_r($settings); 显示什么?尝试调试它 包含密钥的是我的 jwt 设置,请参阅我的新评论 【参考方案1】:

如果我在同一个函数中解码,它会返回解码后的 JWT,但如果我在其他函数中解码,则会返回错误。如何将 jwt 传递给其他函数?

$app->post('/login', function ($request, $response) 

$key = "supersecretkeyyoushouldnotcommittogithub";

$input = $request->getParsedBody();
$settings = $this->get('settings'); // get settings array.
$sql = "SELECT id, password FROM users WHERE id= :id";
$sth = $this->db->prepare($sql);
$sth->bindParam("id", $input['id']);
$sth->execute();
$user = $sth->fetchObject();

// verify user id 
if(!$user) 
    return $this->response->withJson(['error' => true, 'message' => 'NO ID '], 404)->withHeader('Content-type', 'application/json;charset=utf-8', 404);

// Compare the input password and the password from database for a validation
if (strcmp($input['password'],$user->password)) 
    return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.'], 404)->withHeader('Content-type', 'application/json;charset=utf-8', 404);  


$payload = array(
    "iat" => time(),
    "exp" => time() + 36000,
    // "id" => $input['id']
    "context" => [
        "user" => [
            "id" => $input['id']
        ]
    ]
);

try 
    $token = JWT::encode($payload, $key); // $token store the token of the user
 catch (Exception $e) 
    echo json_encode($e);


// return $this->response->withJson($payload,200)
//                       ->withHeader('Content-type', 'application/json;charset=utf-8', 200)
//                       ->withHeader('Authorization', $token);

$decoded = JWT::decode($token, $key, array('HS256'));

print_r($decoded);


);

【讨论】:

正如我所写,当您发出请求时,您的令牌无效,请在 $jwt = $request->getHeader("Authorization"); 行之后打印 $jwt 变量。 请编辑您的问题,不要发布更新的问题作为答案。 是的,我的 jwt 是空的。 @pr1nc3 好的,抱歉对堆栈很陌生【参考方案2】:

尝试按照错误的说明进行操作:

$token = JWT::decode($jwt, $settings['jwt']['secret'], ["HS256"]);

您可以查看使用here的示例

【讨论】:

还是同样的错误,顺便说一句,这是错误的一点imgur.com/a/wMhwAAm 它确实用你的代码说类似 Firebase\JWT\JWT::decode(Array, 'supersecretkeyy...', Array) 。但是用我的代码,它说 Firebase\JWT\JWT::decode(Array, 'supersecretkeyy...', "HS256") 关键错误是Wrong number of segments,您的令牌不是有效的JWT,请打印您传递给decode函数的内容 如果这有助于解决问题,请接受最佳答案 ;)

以上是关于JWT decode() 必须是数组错误类型的主要内容,如果未能解决你的问题,请参考以下文章

json_decode()相关报错

JsonWebToken 遇到问题; JsonWebToken 错误:必须提供 JWT

/auth/jwt/refresh decode() 的 TypeError 使用 Djoser 获得了意外的关键字参数“验证”

JSON解码致命错误:不能使用stdClass类型的对象作为数组

错误信息查找管道必须是字符串,是数组类型

Spring Boot > 2.2.7 的令牌类型为“at+jwt”时 JWT 错误的解码