有图有真相:带你实现现流行的权限验证
摘要:本文通过实例演示 JWT 实现登录授权流程。通过与传统的 session、cookie 和 token 机制进行对比,分析其中的优缺点。
JWT 是什么
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。它是有三部分组成,示例如下,具体的讲解如下(jwt 是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。
它是由一个"."号隔开、三部分组成。
第一部分是 header 信息,
第二部分是 Payload,有固定的六个部分和自定义数据组成,自定义数据看自己的情况需要来定义,是可以省去的。
第三部分是 Signature(是对前两部分加密得来的)。由于前两部分是公开透明的数据,因此防止数据的篡改和泄露,我们需要加密处理。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
最终生成的就是上面很长的一段字符串了。
为什么会使用 JWT
这就需要从我们传统的认证模式来说了,传统的认证模式是基于 session 和 cookie 来实现用户的认证和鉴权。具体的流程模式如下图。
(图一)Session 与 Cookie 认证与鉴权
1.客户端向服务端发送一个 http 请求。
2.服务端在收到客户端的请求时,生成一个唯一的 sessionid,
这里需要将该生成的 session 存储在服务端,这个 sessionid 存储具体的 session 内容,默认的是文件存储,当然我们可以修改具体的存储方式,例如数据库存储。
3.客户端在接受到这个 sessionid 时,存在 cookie 里面,每次请求时携带该 sessionid。
4.服务端在接收到客户端的请求之后,根据客户端发送的 sessionid 来进行认证与授权。
这里也推荐一下自己之前分享的一篇有关 session 于 cookie 的知识点。session 与 cookie 详解
(图二)传统的 token 授权
1.客户端向服务端发送一个 http 请求。
2.服务端在收到客户端的请求之后,生成一个唯一 token,
这里需要将该生成的 token 存储在服务端,至于怎么存,可以和上面 session 与 cookie 的方式一致。也可以存在缓存数据库中,如 redis,memcached。
3.服务端将该 token 返回给客户端,客户端存在本地,可以存请求头 header 中,也可以存在 cookie 中,同时也可以存在 localstorage 中。
4.向服务端发送请求时,携带该 token,服务端进行认证或者授权。
(图三)JWT 认证模式
1.客户端向服务端发送一个 http 请求。
2.服务端根据 jwt 的生成规则,生成一个 token,并返回给客户端,这里服务端是不需要存储的。
3.客户端在接受到该 token 时,存在客户端。
4.客户端向服务端发送请求时,服务端对请求的 token 进行解析,如果发现解析出来的数据和生成的数据是一致的代表是一个合法的 token,则进行相应的操作。
基于 session 和 cookie 的认证和鉴权模式有什么好与不好的地方呢?
通过上面几张图,我们也大致可以看得出来,基于 session 都是需要服务端存储的,而 JWT 是不需要服务端来存储的。针对以上几点,总结如下:
一、缺点
1.容易遇到跨域问题。不同域名下是无法通过 session 直接来做到认证和鉴权的。
2.分布式部署的系统,需要使用共享 session 机制
3.容易出现 csrf 问题。
二、优点
1.方便灵活,服务器端直接创建一个 sessionid,下发给客户端,客户端请求携带 sessionid 即可。
2.session 存储在服务端,更加安全。
3.便于服务端清除 session,让用户重新授权一次。
JWT 与 session 有什么区别呢?
JWT 是基于客户端存储的一种认证方式,然而 session 是基于服务端存储的一种认证方式。JWT 虽然不用服务端存储了,也可以避免跨域、csrf 等情况。但也存在如下几个不太好的地方。
1.无法清除认证 token。由于 JWT 生成的 token 都是存储在客户端的,不能有服务端去主动清除,只有直到失效时间到了才能清除。除非服务端的逻辑做了改变。
2.存储在客户端,相对服务端,安全性更低一些。当 JWT 生成的 token 被破解,我们不便于清除该 token。
如何使用 JWT
这里推荐使用 GitHub 上面人家封装好的包,这里我使用的是 firebase/php-jwt,在项目中直接使用即可安装成功。
composer require firebase/php-jwt
接下来创建一个控制器,我这里使用的 ThinkPHP5.1 的框架
通过访问第一个方法,可以生成下图一段字符串
我们将上图中的字符串复制到第二图中的 $jwt 变量,访问第二个方法即可解析出具体的数据。
本文分享自华为云社区《[图解]JWT 实现用户权限验证体系》,原文作者:A 梦多啦 A 。
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/8ec5b33b6606405933e9a7c62】。文章转载请联系作者。
评论