我正在尝试为我的RESTful api使用JWT实现无状态身份验证。
AFAIK, JWT基本上是在REST调用期间作为HTTP头传递的加密字符串。
但是如果有窃听者看到请求并窃取令牌怎么办?然后他就能用我的身份伪造申请了?
实际上,这个问题适用于所有基于令牌的身份验证。
如何预防呢?像HTTPS这样的安全通道?
我正在尝试为我的RESTful api使用JWT实现无状态身份验证。
AFAIK, JWT基本上是在REST调用期间作为HTTP头传递的加密字符串。
但是如果有窃听者看到请求并窃取令牌怎么办?然后他就能用我的身份伪造申请了?
实际上,这个问题适用于所有基于令牌的身份验证。
如何预防呢?像HTTPS这样的安全通道?
当前回答
我知道这是一个老问题,但我认为我可以在这里放弃0.5美元,也许有人可以改进或提供一个完全否定我的方法的论点。 我正在通过HTTPS (ofc)在RESTful API中使用jwt。
要做到这一点,你应该总是发出短期令牌(取决于大多数情况下,在我的应用程序中,我实际上将exp声明设置为30分钟,ttl为3天,所以你可以刷新这个令牌,只要它的ttl仍然有效,令牌还没有被列入黑名单)
对于身份验证服务,为了使令牌失效,我喜欢在前面使用内存缓存层(在我的情况下是redis)作为JWT黑名单/禁令列表,这取决于一些标准: (我知道这违反了RESTful哲学,但是存储的文档真的是短命的,因为我将它们的剩余生存时间-ttl声明列入黑名单-)
注意:黑名单令牌不能自动刷新
If user.password or user.email has been updated (requires password confirmation), auth service returns a refreshed token and invalidates (blacklist) previous one(s), so if your client detects that user's identity has been compromised somehow, you can ask that user to change its password. If you don't want to use the blacklist for it, you can (but I don't encourage you to) validate the iat (issued at) claim against user.updated_at field (if jwt.iat < user.updated_at then JWT is not valid). User deliberately logged out.
最后,像所有人一样,正常地验证令牌。
注意2:我建议为jti声明生成并使用一个UUID令牌,而不是使用令牌本身(它真的很长)作为缓存的键。这很好,我认为(不确定,因为它刚刚出现在我的脑海中)你可以使用相同的UUID作为CSRF令牌,通过返回一个安全/非http-only cookie,并使用js正确实现X-XSRF-TOKEN头。这样就避免了为CSRF检查创建另一个令牌的计算工作。
其他回答
客户端应该使用用户密码哈希的一部分来加密http msg被客户端发送到服务器的时间。在创建散列的这一部分时,还应该使用一些服务器密钥加密到令牌中。
服务器可以解密http请求时间,并验证较短的时间延迟。
令牌将改变每个请求。
我们不能只添加请求生成这个JWT令牌的初始主机的ip作为声明的一部分吗?现在,当JWT被窃取并从另一台机器上使用时,当服务器验证这个令牌时,我们可以验证请求的机器ip是否与声明中的ip集匹配。这将不匹配,因此可以拒绝令牌。此外,如果用户试图通过将自己的ip设置为令牌来操作令牌,则令牌将被拒绝,因为令牌已被更改。
对不起,我来晚了一点,但我有类似的担忧,现在想在同样的问题上贡献一些东西。
1) rdegges补充了一个很好的观点,即JWT与“安全”无关,只是验证,如果有人搞砸了有效载荷或没有(签名);SSL有助于防止入侵。
2)现在,如果ssl也以某种方式被破坏,任何窃听者都可以窃取我们的持名令牌(JWT)并模仿真正的用户,下一个可以做的步骤是,从客户端寻求JWT的“持有证明”。
3)现在,通过这种方法,JWT的演示者拥有一个特定的所有权证明(POP)密钥,接收方可以通过加密方式确认请求是否来自同一真实用户。
我参考了占有证明的文章,并对这种方法深信不疑。
如果能有所贡献,我将非常高兴。
干杯(y)
为了处理令牌被盗用的问题,您将每个JWT映射为有效ip列表。
例如,当用户登录一个特定的IP时,当你可以添加该IP为该JWT的有效IP时,当你从另一个IP(用户改变了互联网或JWT被盗,或任何原因)得到这个JWT的请求时,你可以根据你的用例做以下事情:
将CSRF令牌与用户令牌映射,如果它被窃取,那么它的CSRF令牌将不匹配,因为您可以使该用户令牌无效。 您可以向用户提供验证码,以验证他是否是有效用户。如果他输入验证码,然后将该IP添加到该JWT的有效列表中。 您可以注销该用户,然后重新请求登录。 您可以提醒用户您的IP已更改或从不同的位置请求。
您也可以在上述用例中使用5分钟的缓存,而不是每次都检查。
建议是否可以改进。
我知道这是一个老问题,但我认为我可以在这里放弃0.5美元,也许有人可以改进或提供一个完全否定我的方法的论点。 我正在通过HTTPS (ofc)在RESTful API中使用jwt。
要做到这一点,你应该总是发出短期令牌(取决于大多数情况下,在我的应用程序中,我实际上将exp声明设置为30分钟,ttl为3天,所以你可以刷新这个令牌,只要它的ttl仍然有效,令牌还没有被列入黑名单)
对于身份验证服务,为了使令牌失效,我喜欢在前面使用内存缓存层(在我的情况下是redis)作为JWT黑名单/禁令列表,这取决于一些标准: (我知道这违反了RESTful哲学,但是存储的文档真的是短命的,因为我将它们的剩余生存时间-ttl声明列入黑名单-)
注意:黑名单令牌不能自动刷新
If user.password or user.email has been updated (requires password confirmation), auth service returns a refreshed token and invalidates (blacklist) previous one(s), so if your client detects that user's identity has been compromised somehow, you can ask that user to change its password. If you don't want to use the blacklist for it, you can (but I don't encourage you to) validate the iat (issued at) claim against user.updated_at field (if jwt.iat < user.updated_at then JWT is not valid). User deliberately logged out.
最后,像所有人一样,正常地验证令牌。
注意2:我建议为jti声明生成并使用一个UUID令牌,而不是使用令牌本身(它真的很长)作为缓存的键。这很好,我认为(不确定,因为它刚刚出现在我的脑海中)你可以使用相同的UUID作为CSRF令牌,通过返回一个安全/非http-only cookie,并使用js正确实现X-XSRF-TOKEN头。这样就避免了为CSRF检查创建另一个令牌的计算工作。