如何使用纯令牌(令牌作为字符串)从控制器 $jwtManager->decode($jwt) 解析 jwt 令牌
Posted
技术标签:
【中文标题】如何使用纯令牌(令牌作为字符串)从控制器 $jwtManager->decode($jwt) 解析 jwt 令牌【英文标题】:How to parse the jwt token from controller $jwtManager->decode($jwt) using pure token ( token as a string ) 【发布时间】:2019-02-06 01:46:19 【问题描述】:所以我正在使用 Lexik JWT 身份验证包 (Symfony 2.6) 并使用此代码成功创建了用户和令牌:
$userRegistration = new UserRegistration();
$userRegistration->setPassword($request->request->get('password'));
$userRegistration->setEmail($request->request->filter('email'));
$userRegistration->setName($request->request->filter('name'));
$token = $this->jwtManager->create($RegisteredUser);
return $this->responseProvider->ok((object) [
'userId' => $RegisteredUser->getId(),
'token' => $token
]);
回应:
"data":
"userId": 24,
"token": "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE"
当我尝试使用jwtManager->decode
方法解码其他控制器中的当前令牌时,问题开始了:
$jwt = "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE";
$test = $this->jwtManager->decode($jwt);
但是JWTManager::decode()
必须实现接口Symfony\Component\Security\Core\Authentication\Token\TokenInterface
并且不期望给出字符串。
我的目标只是从这个令牌中获取 userId,但找不到如何解码令牌的任何信息。有谁知道如何简单地解码令牌?
【问题讨论】:
【参考方案1】:请在没有任何库的情况下找到我的代码。
function decodeJWTPayloadOnly($token)
$tks = explode('.', $token);
if (count($tks) != 3)
return null;
list($headb64, $bodyb64, $cryptob64) = $tks;
$input=$bodyb64;
$remainder = strlen($input) % 4;
if ($remainder)
$padlen = 4 - $remainder;
$input .= str_repeat('=', $padlen);
$input = (base64_decode(strtr($input, '-_', '+/')));
if (version_compare(php_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4))
$obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
else
$max_int_length = strlen((string) PHP_INT_MAX) - 1;
$json_without_bigints = preg_replace('/:\s*(-?\d'.$max_int_length.',)/', ': "$1"', $input);
$obj = json_decode($json_without_bigints);
return $obj;
【讨论】:
【参考方案2】:在不使用 JWT 库的情况下手动从令牌中获取信息非常简单。
一个 JWT 字符串由 3 部分组成:
base64url 编码的标头和有效负载都是 JSON“对象”和签名。所有 3 个部分都由 .
分隔。
因此,您只需将令牌拆分为 3 个部分,在此处使用 explode
完成,然后解码 base64url 编码字符串 (base64_decode
),最后解码 JSON (json_decode
):
$token = "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJqYWdhZHVAaHViaWktbmV0d29yay5jb20iLCJleHAiOjE1MzYxNTI0MDAsImlhdCI6MTUzNTU0NzYwMH0.B7gnfGdW1ijAIlo9xUI0DwkGaajQAQPBkRx4ChILXRNtpLdwgEl_9gvWdiidFbSXJseS8jslOfuAFUIWATmbNBoWVa3nc8SxkIrKI29xZuN6hB7R-63RH2BKsAVPsEjgTIJoqkkCrfrSum-_d3LEf36jcXqZb8M-GRKI477IwSDDwG_7YK5v0mu8N4TATXhN0tZGNYxp8Y27EI-g0Gmj9BIiobxnqVVoBWHN5J8d-UCrXRq94ifhEiQBxkG9r_eacMscB80n1VsiN2ouKH2kX-HRxRJmcgmydxvR7RcEW-P6koTxkaZJGO6mv7auSudTFlDENpwD4OD7gtn_wMUDS_OuN8WT7rZp8lwKY9f8J9fiGyq5J-8C_HmyjW-h8WhuJmTUaKhCZ-eLgDm4Vs2IQGYkHJEDFumnIZ607MAa1CW1ChAvurqvUqJ3G4TTN4wYqAHpSKz4y8SAMLjO91cedBPH6K5i9lh5htF-mW_htem7e5ornicU_djSccgHbxfXHQYTHCnqLp7-ONfl_p4nmhIEK0wcF0gkBXbIitzeTjy7C_uf_FV1sLPE5cY3PUP42DmHrG4PuXHLv_L1EjErkrpna7pChKA_TPeiZjqMcQoE70sZw8rr8KnRF2hpABdU_M2ZXOt_vF5-T8mLmKqs0LHxE089vVC3xsAh0mUr4FE";
$tokenParts = explode(".", $token);
$tokenHeader = base64_decode($tokenParts[0]);
$tokenPayload = base64_decode($tokenParts[1]);
$jwtHeader = json_decode($tokenHeader);
$jwtPayload = json_decode($tokenPayload);
print $jwtPayload->username;
在最后一行你有想要的信息。
您还可以在https://jwt.io 上检查您的令牌,以查看有效负载中包含哪些字段。在那个网站上也有关于 JWT 的很好的介绍。
【讨论】:
在解码前应该检查令牌是否有效,否则会给出一些偏移错误。【参考方案3】:您可以为此使用 JWTEncoder 服务。
服务名称为lexik_jwt_authentication.jws_provider.lcobucci
或者如果你想要类命名服务使用Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface
你要找的方法是decode()
$jwtEncoder->decode($yourToken);
【讨论】:
但是如果 JWT 过期了,decode() 会抛出 Exception : ( 然后捕获异常.. :) 你不会使用无效的、过期的令牌。以上是关于如何使用纯令牌(令牌作为字符串)从控制器 $jwtManager->decode($jwt) 解析 jwt 令牌的主要内容,如果未能解决你的问题,请参考以下文章