JWT(JSON Web Token)简介及实现

2023-05-16

JWT(JSON Web Token):是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为Json对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用HMAC SHA256或RSA等对JWT进行签名。

JWT的组成:它是一个很长的字符串,中间用点(.)分隔成三个部分它的三个部分依次是:Header(头部)、Payload(载荷)、Signature(签名)。JWT默认是不加密的。

Header:是一个Json对象,描述JWT的元数据,例子如下:alg属性表示签名的算法,默认是HMAC SHA256,写成HS256,也可使用RSA;typ属性表示这个令牌(token)的类型,JWT令牌统一写为JWT;id属性是用户自定义的。最后将此Json对象使用base64url编码成字符串。

{
	"alg": "HS256",
	"typ": "JWT",
	"id": "fengbingchun"
}

Payload:也是一个Json对象,用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用:iss(Issuer):签发人;exp(Expiration Time):过期时间;sub(Subject):主题;aud(Audience):受众;nbf(Not Before):生效时间;iat(Issued At):签发时间;jti(JWT ID):编号。除了官方字段,你还可以在这个部分定义私有字段。最后此Json对象也要使用base64url编码成字符串。例子如下:

{
	"csdn": "https://blog.csdn.net/fengbingchun",
	"github": "https://github.com//fengbingchun"
}

Signature:是对前两部分的签名,防止数据篡改。首先需要指定一个密钥(secret),然后使用Header里面指定的签名算法(默认是HMAC SHA256),按照以下的方式产生签名:算出签名后,也需要把此签名通过base64url编码成字符串。最后把Header、Payload、Signature三个部分编码成的字符串拼成一个字符串,每个部分之间用”点”(.)分隔,形式如xxxx.yyyy.zzzz。

HMACSHA256(base64urlEncode(header) + "." + base64urlEncode(payload), secret)

base64url和base64区别:base64有三个字符+、/和=,在URL里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_,这就是base64url。

一般此JWT会放在HTTP请求的头信息Authorization字段里:

Authorization: Bearer <token>

注:以上内容主要来自网络整理,主要参考:

1. https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

2. https://jwt.io/introduction/

3. https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32

以下是代码实现:

Header和Payload内容如上所示,secret值为:"1234567890+-!@#$%^&*x()_=QF{></?",代码段如下:

int test_jwt()
{
	// encode header
	const char* header = "{\"alg\":\"HS256\",\"typ\":\"JWT\",\"id\":\"fengbingchun\"}";
	int length_header = strlen(header);
	int length_encoded_header = (length_header + 2) / 3 * 4;
	std::unique_ptr<char[]> encoded_header(new char[length_encoded_header]);
	int ret = base64url_encode((const unsigned char*)header, length_header, encoded_header.get());
	if (ret != BASE64_OK) {
		fprintf(stderr, "fail to encode header: %s\n", header);
		return -1;
	}
	fprintf(stdout, "encoded header: %s\n", encoded_header.get());

	// encode payload
	const char* payload = "{\"csdn\":\"https://blog.csdn.net/fengbingchun\",\"github\":\"https://github.com//fengbingchun\"}";
	int length_payload = strlen(payload);
	int length_encoded_payload = (length_payload + 2) / 3 * 4;
	std::unique_ptr<char[]> encoded_payload(new char[length_encoded_payload]);
	ret = base64url_encode((const unsigned char*)payload, length_payload, encoded_payload.get());
	if (ret != BASE64_OK) {
		fprintf(stderr, "fail to encode payload: %s\n", payload);
		return -1;
	}
	fprintf(stdout, "encoded payload: %s\n", encoded_payload.get());

	// signature
	std::string buffer;
	buffer.append(encoded_header.get(), strlen(encoded_header.get()));
	buffer.append(".");
	buffer.append(encoded_payload.get(), strlen(encoded_payload.get()));

	//const unsigned char key[] = { // 32 bytes
	//	0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
	//	0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
	//	0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f };
	const char key[] = { // 32 bytes
		'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-',
		'!', '@', '#', '$', '%', '^', '&', '*', 'x', '(', ')', '_',
		'=', 'Q', 'F', '{', '>', '<', '/', '?' };
	std::unique_ptr<unsigned char[]> signature(new unsigned char[EVP_MAX_MD_SIZE]);

	HMAC_CTX* ctx = HMAC_CTX_new();
	HMAC_CTX_reset(ctx);
	const EVP_MD* engine = EVP_sha256();

	unsigned int length_signature;
	HMAC_Init_ex(ctx, key, sizeof(key), engine, nullptr);
	HMAC_Update(ctx, reinterpret_cast<const unsigned char*>(buffer.c_str()), buffer.length());
	HMAC_Final(ctx, signature.get(), &length_signature);
	HMAC_CTX_free(ctx);

	// encode signature
	int length_encoded_signature = (length_signature + 2) / 3 * 4;
	std::unique_ptr<char[]> encoded_signature(new char[length_encoded_signature]);
	ret = base64url_encode(signature.get(), length_signature, encoded_signature.get());
	if (ret != BASE64_OK) {
		fprintf(stderr, "fail to encode signature\n");
		return -1;
	}
	fprintf(stdout, "encoded signature: %s\n", encoded_signature.get());

	buffer.append(".");
	buffer.append(encoded_signature.get(), strlen(encoded_signature.get()));
	fprintf(stdout, "jwt result: %s\n", buffer.c_str());

	return 0;
}

上面的HMAC-SHA256是调用OpenSSL的接口实现的,也可调用bearssl接口实现,代码段如下:

	br_hmac_key_context key_ctx;
	br_hmac_context ctx;
	br_hmac_key_init(&key_ctx, &br_sha256_vtable, key, sizeof(key));
	br_hmac_init(&ctx, &key_ctx, 0);
	size_t length_signature = br_hmac_size(&ctx);

	br_hmac_update(&ctx, buffer.c_str(), buffer.length());
	std::unique_ptr<unsigned char[]> signature(new unsigned char[length_signature]);
	size_t length_signature2 = br_hmac_out(&ctx, signature.get());

采用OpenSSL和bearssl结果完全一致,执行结果如下所示:

将上面的Header、Payload、secret值填入jwt.io,得到的结果与程序实现结果一致,如下图所示:

以上代码段的完整code见:GitHub/OpenSSL_Test

GitHub:https://github.com/fengbingchun/OpenSSL_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JWT(JSON Web Token)简介及实现 的相关文章

  • 第27章 LTDC/DMA2D—液晶显示

    本章参考资料 xff1a STM32F76xxx参考手册 2 STM32F7xx 规格书 库帮助文档 STM32F779xx User Manual chm 关于开发板配套的液晶屏参数可查阅 5 0寸液晶屏数据手册 配套资料获知 27 1
  • GB 9706.1-2020 医用电气设备第1部分:基本安全和基本性能的通用要求-1

    这是份什么文件 这是一份中华人民共和国国家标准 xff0c 具体为GB9706 1 2020 xff0c 标准适用于医用电气设备 xff0c 并规定了医用电气设备基本安全和基本性能的通用要求 主要涵盖了医疗电器设备与患者接触的各种要求 xf
  • 关于图床使用

    安装windows终端 Windows 终端安装 Microsoft Learn 安装oh my posh 安装scoop xff08 后续都使用PowerShell 7 2 10 xff09 xff1a gt Set ExecutionP
  • 关于pyqt的一些用法

    QT原生是C 43 43 xff0c pyqt基于python语言 关于插件 xff1a 安装一个PyUIC xff0c 一个Qt Designer 点击Qt Designer可以出来ui配置页面 xff0c 和qt原生IDE基本一样 上面
  • python从单独的文件中获取配置信息

    可以新建一个configure json文件 xff0c 里面放置json格式的字符串 比如 xff1a deviceMAC1 12412421413 deviceMAC 12413232 name 123123 使用下述程序即可获取jso
  • 解决串口工具串口号改变的问题(借助python和ch344/8)

    串口工具一般在插不同usb口的时候 xff0c 识别出来的串口号不一致 xff0c pl2303可以固定 xff0c 但是更换电脑后也会变化 xff0c 可以借助沁恒家的一款串口一转多的工具 xff0c ch344或ch348 xff0c
  • python将监听到的串口信息实时保存到日志

    尽量在一个单独的线程中运行 stim thread span class token operator 61 span threading span class token punctuation span Thread span clas
  • 技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器

    技能梳理37 64 stm32 43 按键 43 光耦 43 锁存 43 串行转并行 43 继电器 1 项目简介 2 实现逻辑 3 应用场景 主从机有线控制 开关操作 4 核心代码梳理 span class token comment 根据
  • 技能梳理38@stm32+CC2530+超声波+光敏+oled

    技能梳理38 64 stm32 43 CC2530 43 超声波 43 光敏 43 oled 1 项目简介 2 实现逻辑 主从机使用zigbee通信 主机oled显示当前停车场位置图 从机通过超声波和光敏一起检测是否有车 当某位置车辆进出
  • 图文手把手教程--ESP32 OTA空中升级(VSCODE+IDF)

    本文内容 1 xff09 使用hello world例程 xff0c 编译生成hello world bin文件 xff0c 并且开启HTTP本地服务器 2 xff09 使用simple ota example例程 xff0c 通过HTTP
  • HTML URL 编码参考手册-------转载

    一 基础知识点 xff1a web浏览器通过URL从WEB服务器请求页面 在线URL编码解码工具 UrlEncode编码 UrlDecode解码在线工具 二 URL编码作用 xff1a 1 URL编码将字符转换为可通过因特网传输的格式 xf
  • 第28章 LTDC—液晶显示中英文

    本章参考资料 xff1a STM32F76xxx参考手册 STM32F7xx 规格书 库帮助文档 STM32F779xx User Manual chm 关于开发板配套的液晶屏参数可查阅 5 0寸液晶屏数据手册 xff08 或 7 0 寸数
  • SFTP get数据提示错误:cannot download non-regular file

    原因 xff1a 这是由于sftp基本客户端不允许进行递归下载 xff0c 或者是对一个文件夹下载 解决方案 xff1a 需要进去目录下载一个具体的文件 可以看看这个报错是否由于自己讲一个文件夹当成了自己需要下载的文件进行了下载
  • 使用wireshark过滤/查找协议里面的特定内容

    一 使用wireshark命令过滤 xff1a 1 tcp的载荷 xff1a tcp contains 34 api 34 说明 xff1a 在tcp报文中过滤出含有 api 内容的报文 xff1b 如下图 xff1a 2 其它类型协议同理
  • 两步解决科来数据包生成器找不到网卡的问题

    1 下载科来数据包生成器 xff0c 按照默认配置安装即可 xff1a http www colasoft com cn download packet builder php 2 部分同学安装完成后 xff0c 在准备发包时会发现 xff
  • 离线安装selenium

    1 在线情况下最简单直接cmd xff1a cmd环境下 xff0c 用pip install selenium命令安装即可 2 离线安装 xff1a xff08 1 xff09 https pypi org project seleniu
  • vim命令进阶

    显示当前位置行数 nu 显示所有行数 set nu 删除n m行 n m d 删除n 结尾行 n d
  • Centos2步配置本地yum源

    1 进入目录 xff0c 将其中的原有yum源配置转到备份目录当中 cd etc yum repos d mkdir backup mv repo backup 2 新建本地的yum源配置文件 vim local repo 输入一下内容 j
  • Linux4步快速搭建DNS服务器

    1 下载DNS服务器软件 xff1a yum install y bind 2 配置基本配置文件 xff1a vim etc named conf 3 配置域名文件 xff1a vim var named db cn zone 4 重启服务
  • 海康OSD水印

    设置 OSD 字符叠加参数 64 param iUserID loginId 64 param iChan 通道号 64 param contents 内容 public static void SetOSDString int iUser

随机推荐

  • STM32芯片配置错误SWD功能被占用时的下载方法.

    最近在用STM32CubeMX配置STM32芯片 可以配置时钟 管脚 SPI串口等 免去了复杂的计算过程 不用记各种功能寄存器 相当的方便 用过的都说好 强烈推荐大家一试 但刀太锋利了用不熟练也容易误伤 在分配IO口功能的过程中 忘记了SW
  • STM32核心的电源管理器程序卡死现象的分析与解决

    某个项目中的电源管理器在外场频繁出现通讯中卡死现象 该电源管理器内部有多路DC DC主要起电源适配 电源管理及监控作用 控制核心为STM32F103RET7 主要任务为AD采集16路模拟电压 xff0c 控制4路电源通断 xff0c 2路串
  • 第29章 电容触摸屏—触摸画板

    本章参考资料 xff1a STM32F76xxx参考手册 STM32F7xx 规格书 库帮助文档 STM32F779xx User Manual chm 关于开发板配套的触摸屏参数可查阅 5 0寸触摸屏面板说明 xff0c 触摸面板配套的触
  • SBUS2 协议初探

    SBUS2和SBUS的区别 1 xff1a 总线类型不一样 sbus是单向传输 xff0c 只做控制使用 xff0c 不做输入 SBUS2是非标准的双向总线 xff0c 可以做控制输出 xff0c 也可以做信息输入 2 xff1a 结束符不
  • IAR 中如何调用EmEditor

    IAR 中如何调用EmEditor 文本编辑器我一直都用EmEditor Emeditor是一款很优秀的纯文本编辑器 xff0c 它对中日韩等亚洲字符集支持的很好 xff0c 不仅有语法高亮显示功能 xff0c 搜索替换功能也是近乎可爱的强
  • 花了一下午,弄明白四个名词 USCI,USI,LIN,IrDa

    最近在看MSP的程序 xff0c TI的官方例子程序 xff0c 有些名词看了却不知道什么意思 xff0c 本着穷根问底的态度 xff0c 上网搜索 xff0c 花了一下午 xff0c 弄明白四个名词 USCI xff0c USI xff0
  • Cadence 17.2学习笔记--显示元件丝印及元件标号的设置

    快捷键Ctrl 43 F5 调出Color Dialog 左侧菜单第三项Geometry选项 钩选图中Silkscreen Top或Silkscreen Bottom可打开或关闭元件外形丝印的显示 同样Color Dialog对话框 左侧菜
  • 【Android UI】色板

    Hex CodeColor FFFFFF FFFFCC FFFF99 FFFF66 FFFF33 FFFF00 FFCCFF FFCCCC FFCC99 FFCC66 FFCC33 FFCC00 FF99FF FF99CC FF9999 F
  • 对称加密算法AES简介及在OpenSSL中使用举例

    高级加密标准 AES Advanced Encryption Standard 由美国国家标准和技术协会 NIST 于2000年公布 xff0c 它是一种对称加密算法 xff0c 用来替代DES AES也称为Rijndael算法 xff0c
  • 基于Hash的消息认证码HMAC简介及在OpenSSL中使用举例

    HMAC Hash based Message Authentication Code xff1a 基于Hash的消息认证码 xff0c 是一种通过特别计算方式之后产生的消息认证码 MAC xff0c 使用密码散列函数 xff0c 同时结合
  • 在Windows和Linux上编译gRPC源码操作步骤(C++)

    gRPC最新发布版本为v1 23 0 xff0c 下面以此版本为例说明在Windows和Linux下编译过程 Windows7 10 vs2103编译gRPC源码操作步骤 xff1a 1 需要本机已安装Git CMake Perl Go y
  • gRPC简介及简单使用(C++)

    gRPC是一个现代的 开源的 高性能远程过程调用 RPC 框架 xff0c 可以在任何平台运行 gRPC使客户端和服务器端应用程序能够透明地进行通信 xff0c 并简化了连接系统的构建 gRPC支持的语言包括C 43 43 Ruby Pyt
  • C语言中select函数简介及使用

    select函数用来检查套接字描述符 sockets descriptors 是否已准备好读 写 xff0c 提供了一种同时检查多个套接字的方法 Linux中select函数的声明在 usr include x86 64 linux gnu
  • VS Code离线安装C/C++插件cpptools-linux-aarch64.vsix

    一 问题 最近VS Code连接jetson nano xff0c 经常提示加载C C 43 43 插件失败 二 解决方法 根据提示 xff0c 在githup上 https github com microsoft vscode cppt
  • 开源库BearSSL介绍及使用

    BearSSL是用C语言实现的SSL TLS协议 xff0c 它的源码可直接通过git clone https www bearssl org git BearSSL 下载 xff0c 它的license是MIT xff0c 最新版本为0
  • 对称加密算法AES之GCM模式简介及在OpenSSL中使用举例

    AES Advanced Encryption Standard 即高级加密标准 xff0c 由美国国家标准和技术协会 NIST 于2000年公布 xff0c 它是一种对称加密算法 关于AES的更多介绍可以参考 xff1a https bl
  • ASN.1简介及OpenSSL中ASN.1接口使用举例

    ASN 1 Abstract Syntax Notation One 是一套标准 xff0c 是描述数据的表示 编码传输 解码的灵活的记法 它提供了一套正式 无歧义和精确的规则以描述独立于特定计算机硬件的对象结构 OpenSSL的编码方法就
  • 从openssl rsa pem文件中提取公私钥数据实现

    RSA为非对称加密算法 xff0c 关于其介绍可以参考 xff1a https blog csdn net fengbingchun article details 43638013 OpenSSL最新版为 1 1 1g xff0c 在Wi
  • 通过OpenSSL的接口实现Base64编解码

    对openssl genrsa产生的rsa私钥pem文件 xff0c 使用普通的base64解码会有问题 xff0c 如使用https blog csdn net fengbingchun article details 85218653
  • JWT(JSON Web Token)简介及实现

    JWT JSON Web Token xff1a 是一个开放标准 RFC 7519 xff0c 它定义了一种紧凑且自包含的方式 xff0c 用于在各方之间作为Json对象安全地传输信息 由于此信息是经过数字签名的 xff0c 因此可以被验证