2017-04-19 72 views
5

我目前正在使用PHP学习JWT实现,并希望为我的RESTful应用程序使用JWT令牌而不是会话。在智威汤逊有效负载中存储敏感数据安全吗?

在签名制作的,我在这里,我们只是使用Base64有效载荷做这样

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

东西。如果我粘贴https://jwt.io/#debugger这样的站点,Payload将被解密(即使签名是错误的)。

我的问题,

  1. 仅用于发送数据时验证与服务器签名JWT?
  2. 是否不安全以保持敏感数据在有效载荷中?
  3. 如果不安全,有什么办法来保证有效负载?

下面是示例代码我写

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

请在downvoting之前提供意见。如果有什么不对,我会更新我的问题:) –

+0

嗨,根据我参加JWT会议的信息,敏感数据应该保留在数据库中,令牌本身应该只包含快速识别所需的信息,而不是授权。 – Auris

+0

我们应该在upvoting之前提供意见吗? - :)原因downvote评论是罕见的是becasuse所以主持人建议不要偶尔报复downvoting。 – zaph

回答

5

如果我像https://jwt.io/#debugger网站粘贴,有效载荷就会被解密(即使签名是错误的)。

由于第三方没有密钥,因此无法验证签名。 有效负载不被解密 - 它被解码。

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

如果您在Web浏览器的本地存储中拥有令牌,并且您的站点存在XSS漏洞,则窃取该令牌会变得微不足道。攻击者拥有一个有效的JWT已经够糟了(无论如何这个JWT很快就会过期),但是如果它包含敏感数据,那么你真的很麻烦。想象一下,必须通知您网站上的所有用户,他们现在必须改变有关他们自己的敏感数据的各种位,因为可能存在大规模的妥协。

保持JWT轻量级。存储用户ID,他们的角色/授予系统。如果您觉得您需要将敏感数据添加到有效负载中,请尝试并重新考虑您的解决方案。

1

据我所知,你试图拥有一个完整的stateless服务器,所以你想要在令牌中存储敏感数据。

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

因此,最好从数据库中获取敏感数据,因为每次请求都应该触摸你的数据库。

+1

如你所说,拥有一个黑名单或白名单使得它不如无国籍。所以应该避免。只有短命令令牌会更好,所以没有“注销”动作。注销操作只是客户端删除令牌。 – jfadich

+0

短暂到期并不能解决问题。特别是在移动应用程序中,至少您必须拥有用户想要保持登录的选项。(在现代应用程序中,用户永远不会注销)因此,您有某种令牌根本不包含'exp' 。如果用户想要注销,该怎么办?令牌将是有效的! –

+2

让一个没有'exp'的令牌是非常糟糕的做法。拥有认证令牌和刷新令牌会更好(这是大多数谷歌产品的工作原理)。身份验证令牌随每个请求一起发送,以授权请求,但仅在短时间内有效(例如30分钟)。刷新令牌用于在其到期后获取新的授权令牌。刷新标记应该仍然有效,但可能会更长(例如2周),并且可以自行刷新。要注销,客户端将删除这两个令牌。这可以让你的用户总是安全地登录(只需保持新鲜的令牌的秘密) – jfadich

1
  1. JWT仅用于在发送数据时验证服务器签名吗?

不,不仅有签署的JWT (JWS - RFC 7515),还有加密的JWT (JWE - RFC 7516)

  1. 对于Payload中的敏感数据是否不安全?

当JWT加密时,您可以安全地共享敏感数据(除非算法或密钥被泄露)。

但在你的例子中,我看不到任何敏感数据,因此我想知道在你的情况下使用JWE是否真的很重要。 我强烈建议你到read this blog post关于智威汤逊和会议,以及为什么你不应该使用它们(也看看that part 2)。

如果你真的想使用JWE,那么我写了a PHP library,它已经能够加载和创建任何种类的Jose(JWS/JWE),并支持几乎所有的算法,从RFC 7518开箱即用。 可能存在其他库,但没有引用列表(https://jwt.io/仅列出JWS实现)。