JWT 令牌登录和注销
Posted
技术标签:
【中文标题】JWT 令牌登录和注销【英文标题】:JWT token login and logout 【发布时间】:2015-12-31 00:33:08 【问题描述】:您好,我正在创建使用 REST API 端点与服务器端通信的移动原生应用程序。 我以前有开发本机客户端的经验,但我有简单的令牌(随机生成的字符串)存储在 DB 中存储用户信息的同一个表中。因此,它就像浏览器中使用的会话,但每个请求的标头中都有令牌,而不是 cookie。
最近我发现了 JWT 令牌。这似乎是保护私有端点的好方法。您可以从移动客户端请求令牌,前提是您通过 + 登录并获得生成的令牌作为响应。 但重要的一点是,这个令牌没有存储在服务器上的任何地方,服务器使用秘密字来验证令牌,这对于服务器来说是私有的,就像私钥一样。 这对于安全端点来说没问题,但是如果我需要用户会话该怎么办,例如 Facebook、Amazon、Aliexpress 等应用程序如何工作......他们可以在不提供凭据的情况下使用应用程序,只需在商店中导航,但是当用户不想购买时需要登录。在该用户会话保持一段时间之后。 这可以用 JWT 令牌毫无问题地实现,但是当用户需要注销时,在这种情况下该怎么办?令牌未存储在服务器上的任何位置,那么如何销毁此令牌以使其无效?
如果令牌存储在数据库中,则 API 不是无状态的,而 REST API 应该是。 所以一般来说,没有办法让用户在无状态 API 中登录,对吗?
我对如何使用 JWT 令牌实现这一点有一些想法,但据我所知,这也不是无状态 API。
-
创建过期令牌列表
将JWT令牌存储在数据库中,但是如果将其存储在数据库中,这种情况下自我描述令牌(JWT)的目的是什么,据我所知,JWT令牌的主要思想是用令牌保存所有信息。
请建议在这种情况下最好的方法是什么,如果我错了,请纠正我。 谢谢。
【问题讨论】:
【参考方案1】:我是怎么做的:
我生成一个随机id(我称之为验证码)并在用户注册时将其存储在数据库中,将其编码为jwt。
每当使用 jwt 发出任何请求时,我都会检查验证码,如果正确:授予访问权限。
为了让会话像更改密码后一样过期,我更改了数据库中的验证码。
【讨论】:
【参考方案2】:如果您需要注销用户,请提供注销链接。例如,服务器应通过使用任何空数组对令牌进行编码来重置会话数据。用户将有一个有效的会话,但没有有效的信息来验证它们。
登录时的有效令牌
$data = array("id"=>1,"user_type"=>"Admin");
$token = JWT:encode($data, $key);
验证令牌
$token = $_POST['token'];
$data = JWT:decode($data, $key, $hash);
if($data.id)
return "valid token";
else
return "invalid token"
【讨论】:
【参考方案3】:如果您使用的是 JWT,那么您就不能拥有服务器端状态来正确注销用户,而不会违背使用 JWT 的初衷。但是,如果您想这样做,最好的选择是将上次注销日期存储在数据库和 JWT 中,如果这些不匹配您注销用户(在这种情况下不更新日期)。但是,您现在有了服务器端状态。
不过,在数据库中存储已注销的令牌似乎有点过头了。
另一种选择是您可以生成由 CSPRNG 生成的 128 位令牌,使用 SHA-256 将其存储在数据库中,然后在 Web 令牌中使用未散列的值。这样,您可以简单地删除条目以注销用户服务器端。这是更安全的选项,因为您现在可以正确地使服务器上的令牌和会话过期。如果用户更改了他们的密码,或者想通过注销其他会话来保护他们的帐户,您现在可以这样做。
【讨论】:
【参考方案4】:JWT 身份验证基本上发生在客户端和服务器端。
当用户发送用户名和密码进行身份验证时。它对数据库进行检查,如果有效,则会生成一个笑话并将其发送回用户。生成 JWT 令牌有多种 API,您可以查看http://jwt.io/
一旦生成并发送回令牌,它需要与每个请求中的标头一起发送,并且需要在服务器端进行验证,然后再将 API 提供给用户。
无需存储令牌,因为 API 本身将允许您在服务器端对其进行解码。
【讨论】:
注销是我最感兴趣的主要问题以上是关于JWT 令牌登录和注销的主要内容,如果未能解决你的问题,请参考以下文章