让我们从头开始讨论:
JWT 是一种非常现代、简单且安全的方法,可扩展为 Json Web Tokens。 Json Web Tokens 是一种用于身份验证的无状态解决方案。所以不需要在服务器上存储任何会话状态,这对于 RESTful API 来说当然是完美的。
Restful API 应该始终是无状态的,使用 JWT 进行身份验证的最广泛使用的替代方法是使用会话将用户的登录状态存储在服务器上。但是当然没有遵循 RESTful API 应该是无状态的原则,这就是 JWT 之类的解决方案变得流行和有效的原因。
现在让我们了解身份验证如何与 Json Web 令牌一起工作。假设我们的数据库中已经有一个注册用户。因此,用户的客户端首先使用用户名和密码发出 post 请求,然后应用程序检查用户是否存在以及密码是否正确,然后应用程序将为该用户生成唯一的 Json Web Token。
令牌是使用存储在服务器上的秘密字符串创建的。接下来,服务器将该 JWT 发送回客户端,客户端会将其存储在 cookie 或本地存储中。
就像这样,用户通过身份验证并基本上登录到我们的应用程序,而不会在服务器上留下任何状态。
所以服务器实际上并不知道哪个用户实际登录了,但当然,用户知道他已经登录了,因为他有一个有效的 Json Web 令牌,有点像访问受保护部分的通行证应用。
再说一遍,只是为了确保您明白这一点。用户在取回其唯一的有效 Json Web 令牌后立即登录,该令牌未保存在服务器上的任何位置。所以这个过程是完全无状态的。
然后,例如,每次用户想要访问受保护的路线(例如他的用户个人资料数据)时。他将他的 Json Web 令牌连同一个请求一起发送,所以这有点像出示他的护照以访问该路线。
一旦请求到达服务器,我们的应用程序将验证 Json Web Token 是否真的有效,如果用户真的是他所说的那个人,那么请求的数据将被发送到客户端,如果不是,然后会有一个错误告诉用户他不允许访问该资源。
所有这些通信都必须通过 https 进行,因此要保护加密的 Http,以防止任何人都可以访问密码或 Json Web 令牌。只有这样我们才有一个真正安全的系统。
因此,Json Web 令牌看起来像此屏幕截图的左侧部分,该屏幕截图取自 jwt.io 的 JWT 调试器。所以本质上,它是一个由三部分组成的编码字符串。标头、有效负载和签名 现在标头只是关于令牌本身的一些元数据,有效负载是我们可以编码到令牌中的数据,是我们真正想要的任何数据。所以我们想要在这里编码的数据越多,JWT 就越大。无论如何,这两部分只是纯文本,会被编码,但不会加密。
因此任何人都可以对其进行解码和阅读,我们不能在此处存储任何敏感数据。但这根本不是问题,因为在第三部分,所以在签名中,才是真正有趣的地方。签名是使用标头、有效负载和保存在服务器上的秘密创建的。
然后将整个过程称为签署 Json Web 令牌。签名算法采用标头、有效负载和秘密来创建唯一签名。所以只有这个数据加上秘密才能创建这个签名,好吗?
然后与标头和有效负载一起,这些签名形成 JWT,
然后将其发送给客户端。
一旦服务器接收到 JWT 以授予对受保护路由的访问权限,它需要对其进行验证以确定用户是否真的是他声称的那个人。换句话说,它将验证是否没有人更改令牌的标头和有效负载数据。同样,此验证步骤将检查是否没有第三方实际更改 Json Web 令牌的标头或负载。
那么,这种验证实际上是如何工作的?嗯,它实际上很简单。一旦接收到 JWT,验证将获取它的 header 和 payload,以及仍然保存在服务器上的 secret,基本上创建了一个测试签名。
但是当初创建 JWT 时生成的原始签名还在令牌中,对吧?这就是验证的关键。因为现在我们要做的就是将测试签名与原始签名进行比较。
而如果测试签名与原始签名相同,则说明payload和header没有被修改。
因为如果它们已被修改,那么测试签名就必须不同。因此,在这种数据没有更改的情况下,我们可以对用户进行身份验证。当然,如果两个签名
实际上是不同的,好吧,那就意味着有人篡改了数据。
通常通过尝试更改有效负载。但是操纵有效载荷的第三方当然无法访问机密,因此他们无法签署 JWT。
所以原始签名永远不会对应于被操纵的数据。
因此,在这种情况下,验证总是会失败。这是使整个系统正常工作的关键。正是这种魔力让 JWT 变得如此简单,
但也非常强大。