在JWT Payload中存储敏感数据是否安全?

时间:2017-04-19 13:13:18

标签: php jwt

我目前正在学习使用PHP的JWT实现,并希望使用JWT令牌代替我的RESTful应用程序的会话。

在签名创建过程中,我正在做这样的事情

token = base64Header + '.' + base64Payload + '.' + signature  

这里我们只使用base64 Payload。如果我粘贴在https://jwt.io/#debugger之类的网站中,Payload会被解密(即使签名错误)。

我的问题,

  1. JWT仅用于在发送数据时验证服务器的签名吗?
  2. 在Payload中保留敏感数据是不安全的吗?
  3. 如果不安全,有什么方法可以确保有效负载?
  4. 以下是我写的示例代码

    <?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
    

3 个答案:

答案 0 :(得分:9)

  

如果我粘贴在https://jwt.io/#debugger这样的网站上,Payload会被解密(即使签名错误)。

第三方无法验证签名,因为他们没有密钥。 有效载荷不会被解密 - 它会被解码。

理想情况下,您应该在有效负载中存储敏感数据,因为有效负载仅为base64编码且未加密。这意味着任何获得令牌的人都可以通过简单的base64解码来查看有效负载的内容。

如果您在Web浏览器的本地存储中有令牌,并且您的站点有XSS漏洞,那么窃取令牌就变得微不足道了。攻击者有一个有效的JWT(很快就会过期)会很糟糕,但如果它包含敏感数据,那么你真的遇到了麻烦。想象一下,必须通知您网站上的所有用户,他们现在必须更改有关他们自己的各种敏感数据,因为可能存在质量损失。

保持JWT的轻量级。存储用户ID,他们的角色/资助与系统。如果您认为必须将敏感数据添加到有效负载,请尝试并重新考虑您的解决方案。

答案 1 :(得分:2)

  1. JWT仅用于在发送数据时验证服务器的签名吗?
  2. 不,不仅签署了JWT (JWS - RFC 7515),还加密了JWT (JWE - RFC 7516)

    1. 在Payload中保留敏感数据是不安全的吗?
    2. 当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服务器,因此您甚至希望在令牌中存储敏感数据。

但是你的服务器不能完全无状态。因为对于注销功能,您必须具有黑名单白名单才能使令牌无效。因此,在每个请求中,您必须触摸数据库。如果您没有黑名单白名单,即使用户退出,令牌仍然有效。

因此,从数据库中获取敏感数据会更好,因为您应该根据每个请求触摸数据库。