JSON Web Token跨域认证解决方案 使用详解

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: JSON Web Token跨域认证解决方案 使用详解

> JWT 是什么?

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。它是有三部分组成,示例如下,具体的讲解如下(jwt 是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjMfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

它是由一个"."号隔开、三部分组成。 第一部分是 header 信息,

{
  "alg": "HS256",// 加密的算法
  "typ": "JWT"// 加密的方式,填写JWT
}

第二部分是 Payload,有固定的六个部分和自定义数据组成,自定义数据看自己的情况需要来定义,是可以省去的。

'iss' => 'https://www.qqdeveloper.com',// 签发人
'exp' => time() + 86400,// 过期时间(这里的有效期时间为1天)
'sub' => '主题内容',// 主题
'aud' => '受众内容',// 受众
'nbf' => $time,// 生效时间
'iat' => $time,// 签发时间
'jti' => 123,// 编号

第三部分是 Signature(是对前两部分加密得来的)。由于前两部分是公开透明的数据,因此防止数据的篡改和泄露,我们需要加密处理。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

第一部分的加密方式(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

最终生成的就是上面很长的一段字符串了。

> 为什么会使用 JWT

这就需要从我们传统的认证模式来说了,传统的认证模式是基于 session 和 cookie 来实现用户的认证和鉴权。具体的流程模式如下图。

image.png

(图一)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,服务端进行认证或者授权。

image.png

(图三)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 的框架

use think\Controller;
use Firebase\JWT\JWT;
class Test extends Controller
{
    private $key = 'jwtKey';
    // 生成JWT
    public function createJwt()
    {
        $time  = time();
        $key   = $this->key;
        $token = [
            'iss' => 'https://www.qqdeveloper.com',// 签发人
            'exp' => $time + 86400,// 过期时间(这里的有效期时间为1天)
            'sub' => '主题内容',// 主题
            'aud' => '受众内容',// 受众
            'nbf' => $time,// 生效时间
            'iat' => $time,// 签发时间
            'jti' => 123,// 编号
            // 额外自定义的数据
            'data' => [
                'userName' => '编程浪子走四方'
            ]];
        // 调用生成加密方法('Payloadn内容','加密的键',['加密算法'],['加密的可以'],['JWT的header头'])
        $jwt = JWT::encode($token, $key);
        return json(['data' => $jwt]);
    }
    // 解析JWT
    public function analysisJwt()
    {
        try {
            $key = $this->key;
            $jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImV4cCI6MTU2ODA5NjE4MCwic3ViIjoiXHU0ZTNiXHU5ODk4XHU1MTg1XHU1YmI5IiwiYXVkIjoiXHU1M2Q3XHU0ZjE3XHU1MTg1XHU1YmI5IiwibmJmIjoxNTY4MDA5NzgwLCJpYXQiOjE1NjgwMDk3ODAsImp0aSI6MTIzLCJkYXRhIjp7InVzZXJOYW1lIjoiXHU3ZjE2XHU3YTBiXHU2ZDZhXHU1YjUwXHU4ZDcwXHU1NmRiXHU2NWI5In19.kHb_9Np0zjE25YE9czUEGvmFPYtqMJT9tuZzJTuMZl0';
            // 调用解密方法('JWT内容','解密的键,和加密时的加密键一直','加密算法')
            $decoded = JWT::decode($jwt, $key, array('HS256'));
            return json(['message' => $decoded]);
        } catch (\Exception $exception) {
            return json(['message' => $exception->getMessage()]);
        }
    }
}

通过访问第一个方法,可以生成下图一段字符串

01ebd755782e4c909dad0843d3544acf.jpeg 我们将上图中的字符串复制到第二图中的$jwt 变量,访问第二个方法即可解析出具体的数据。

01ebd755782e4c909dad0843d3544acf.jpeg




目录
相关文章
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
169 3
|
1月前
|
存储 JSON 安全
如何使用 JSON Web Tokens 进行身份验证?
总的来说,JWT 是一种强大而灵活的身份验证方式,通过正确使用和管理,可以为应用提供可靠的身份验证机制,同时提高系统的可扩展性和安全性。在实际应用中,需要根据具体的需求和场景,合理设计和实施 JWT 身份验证方案。
116 63
|
4月前
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
74 1
|
3月前
|
小程序 前端开发 中间件
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
本文介绍了如何在ThinkPHP框架中配置跨域请求,使用了TP内置的跨域类`\think\middleware\AllowCrossDomain::class`。文章还讨论了小程序和web网页在跨域请求格式上的区别,并提供了解决方案,包括修改跨域中间件源码以支持`Origin`和`token`。此外,还介绍了微信小程序跨域请求的示例和web网页前端发送Axios跨域请求的请求拦截器配置。
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
|
2月前
|
移动开发 前端开发 小程序
浅谈-web屏幕适配的解决方案
浅谈-web屏幕适配的解决方案
57 0
浅谈-web屏幕适配的解决方案
|
3月前
|
前端开发 Python
前后端分离的进化:Python Web项目中的WebSocket实时通信解决方案
在现代Web开发领域,前后端分离已成为一种主流架构模式,它促进了开发效率、提升了应用的可维护性和可扩展性。随着实时数据交互需求的日益增长,WebSocket作为一种在单个长连接上进行全双工通讯的协议,成为了实现前后端实时通信的理想选择。在Python Web项目中,结合Flask框架与Flask-SocketIO库,我们可以轻松实现WebSocket的实时通信功能。
73 2
|
2月前
|
JavaScript 前端开发 安全
轻松上手Web Worker:多线程解决方案的使用方法与实战指南
轻松上手Web Worker:多线程解决方案的使用方法与实战指南
63 0
|
2月前
|
Java 应用服务中间件 Spring
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
【终极解决方案】Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
43 0
|
4月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
67 0
|
2月前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道