我目前正在学习使用PHP的JWT实现,并希望使用JWT令牌代替我的RESTful应用程序的会话。
在签名创建过程中,我正在做这样的事情
token = base64Header + '.' + base64Payload + '.' + signature
这里我们只使用base64 Payload。如果我粘贴在https://jwt.io/#debugger之类的网站中,Payload会被解密(即使签名错误)。
我的问题,
以下是我写的示例代码
<?php
$headers = base64_encode(json_encode([
"typ" => "JWT",
"alg" => "HS256"
]));
$claims = base64_encode(json_encode([
"sub" => "1234567890",
"name" => "John Doe",
"admin" => true,
"jti" => "870a3de5-ea7b-4062-abef-11180e530f5a",
"iat" => 1492603378,
"exp" => 1492606978
]));
$payload = $headers.".".$claims;
$signature = base64_encode(hash_hmac("sha256", $payload, 'secret', true));
$encodedJWT = $payload.".".$signature;
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6Ijg3MGEzZGU1LWVhN2ItNDA2Mi1hYmVmLTExMTgwZTUzMGY1YSIsImlhdCI6MTQ5MjYwMzM3OCwiZXhwIjoxNDkyNjA2OTc4fQ.nvw-bAUgr7H_xr3q8_Yz8rCNtMohtn2YlCmcLoLBWlc
答案 0 :(得分:9)
如果我粘贴在https://jwt.io/#debugger这样的网站上,Payload会被解密(即使签名错误)。
第三方无法验证签名,因为他们没有密钥。 有效载荷不会被解密 - 它会被解码。
理想情况下,您应该不在有效负载中存储敏感数据,因为有效负载仅为base64编码且未加密。这意味着任何获得令牌的人都可以通过简单的base64解码来查看有效负载的内容。
如果您在Web浏览器的本地存储中有令牌,并且您的站点有XSS漏洞,那么窃取令牌就变得微不足道了。攻击者有一个有效的JWT(很快就会过期)会很糟糕,但如果它包含敏感数据,那么你真的遇到了麻烦。想象一下,必须通知您网站上的所有用户,他们现在必须更改有关他们自己的各种敏感数据,因为可能存在质量损失。
保持JWT的轻量级。存储用户ID,他们的角色/资助与系统。如果您认为必须将敏感数据添加到有效负载,请尝试并重新考虑您的解决方案。
答案 1 :(得分:2)
不,不仅签署了JWT (JWS - RFC 7515),还加密了JWT (JWE - RFC 7516)。
当JWT加密时,您可以安全地共享敏感数据(除非算法或密钥被泄露)。
但在您的示例中,我看不到敏感数据,因此我想知道在您的情况下使用JWE是否真的很重要。 我强烈建议你read this blog post关于JWT和会话,以及为什么不应该将它们用于此目的(另请参阅that part 2)。
如果你真的想使用JWE,那么我写了a PHP library已经能够加载和创建任何类型的Jose(JWS / JWE)并且几乎支持RFC 7518的所有算法的盒子。 可能存在其他库,但没有引用列表(https://jwt.io/仅列出JWS实现)。
答案 2 :(得分:1)
据我了解,您正在尝试拥有一个完整的stateless
服务器,因此您甚至希望在令牌中存储敏感数据。
但是你的服务器不能完全无状态。因为对于注销功能,您必须具有黑名单或白名单才能使令牌无效。因此,在每个请求中,您必须触摸数据库。如果您没有黑名单或白名单,即使用户退出,令牌仍然有效。
因此,从数据库中获取敏感数据会更好,因为您应该根据每个请求触摸数据库。