当前位置: 首页 > news >正文

JWT究竟是什么呢?

译者按:如果你还在使用session验证用户的话,是时候了解一下JWT了!

  • 原文:What the heck is JWT anyway?
  • 译者:Fundebug

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java线上bug实时监控。真的是一个很好用的bug监控服务,众多大佬公司都在使用。

JWT(JSON Web Token)究竟是什么呢?它有什么用?这篇文章将为你揭开谜底。

首先,我们不妨看一下IETF(Internet Engineering Task Force)对JWT的权威定义:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

啊!什么鬼?! 水平有限,这样的定义我就不翻译了...

简单地说,JWT是一个字符串,我们在发起网络请求时,将其放在header或者url中,这样可以保证传递的数据被篡改时能被我们发现,保证安全性。

示例xxxxx.yyyyy.zzzzz即为JWT:

http://www.example.com/private/?token=xxxxx.yyyyy.zzzzz

小伙伴应该注意到了,JWT由3部分组成,使用两个点区分。如下:

header.payload.signature

那么,header, payload和signature分别指的是什么呢?

Header

header所表示的JSON对象通常由2个部分组成:token的类型,即"JWT"; token所采用的hash算法,例如HMAC SHA256或者RSA。

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

然后,这个JSON对象采用Base64Url编码变成字符串,作为JWT的第一部分。

var header = {
    alg: 'HS256',
    typ: 'JWT'
};

// 将JSON对象使用base64编码为字符串
var encoded_header = Buffer.from(JSON.stringify(header)).toString('base64');
console.log(encoded_header); // 打印: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

// 将base64编码的字符串解析为JSON对象
var decoded_header = JSON.parse(Buffer.from(encoded_header, 'base64').toString());
console.log(decoded_header); // 打印: { alg: 'HS256', typ: 'JWT' }

可知,header只是进行了编码,而非加密,其过程是可逆的。

Payload

payload为JWT的第二部分,其JSON对象包含一系列键值对(key/value)。其中,有些预定义键有特殊含义,比如iat、exp等,iat表示JWT生成的实际,而exp代表JWT过期的时间。开发者可以使用其他非预定义的键用于传输数据。

{
   "exp": "2100-01-01",
   "message": "Hello, Fundebug!"
}

然后,这个JSON对象采用Base64Url编码变成字符串,作为JWT的第二部分。

var payload = {
    exp: '2100-01-01',
    message: 'Hello, Fundebug!'
}

// 将JSON对象使用base64编码为字符串
var encoded_payload = Buffer.from(JSON.stringify(payload)).toString('base64');
console.log(encoded_payload); // 打印: eyJleHAiOiIyMTAwLTAxLTAxIiwibWVzc2FnZSI6IkhlbGxvLCBGdW5kZWJ1ZyEifQ==

// 将base64编码的字符串解析为JSON对象
var decoded_payload = JSON.parse(Buffer.from(encoded_payload, 'base64').toString());
console.log(decoded_payload); // 打印: { exp: '2100-01-01', message: 'Hello, Fundebug!' }

特别注意,payload只是进行了编码,而非加密,其过程是可逆的。因此,JWT绝不是用来进行加密通信的。

Signature

signatrue,即签名,是JWT的第三部分。它由编码的header和payload,使用用户指定的密钥secret,采用header中指定的哈希算法生成。Node.js自带的Crypto可以来演示signatrue是如何生成的:

var header = {
    alg: 'HS256',
    typ: 'JWT'
};

// 使用base64编码header
var encoded_header = Buffer.from(JSON.stringify(header)).toString('base64');


var payload = {
    exp: '2100-01-01',
    message: 'Hello, Fundebug!'
}

// 使用base64编码pyload
var encoded_payload = Buffer.from(JSON.stringify(payload)).toString('base64');


const crypto = require('crypto');
var secret = '$T697UaW6QTWsw}rrt%*P6)ia';

// 生成签名signature
var signature = crypto.createHmac('sha256', secret).update(encoded_header + '.' + encoded_payload).digest('base64');
console.log(signature); // 打印: JiOyrHVgyTTSts6mYQpChRHO7J2/hNU4dOYkgeLthKE=

signature是根据payload生成的,两者是一一对应的,这样可以保证payload的数据不被篡改,除非密钥secret泄漏。

最终生成的JWT为:

var token = `${encoded_header}.${encoded_payload}.${signature}`;
console.log(token) // 打印: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMTAwLTAxLTAxIiwibWVzc2FnZSI6IkhlbGxvLCBGdW5kZWJ1ZyEifQ==.JiOyrHVgyTTSts6mYQpChRHO7J2/hNU4dOYkgeLthKE=

当收到JWT时,可以采用同样的算法和密钥生成签名signature,如果一致,说明数据没有被篡改。

很重要一点在于,JWT是用于验证而非加密,任何人即使没有密钥secret,header与payload中的数据都是可以获取的。

使用jwt.io,可以进行JWT的编码、解码和验证:

图片描述

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了6亿+错误事件,得到了Google、360、金山软件等众多知名用户的认可。欢迎免费试用!

图片描述

版权声明

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/07/12/what-is-jwt/

相关文章:

  • Win#password;;processon #clone;;disassemble;;source find
  • PHP全栈开发(三):CentOS 7 中 PHP 环境搭建及检测
  • V神新论文|STARKs III: Into the Weeds(下)
  • Docker学习笔记三:Docker镜像image
  • python学习之老男孩python全栈第九期_day029知识点总结——configparser模快、logging模块...
  • python爬虫知识点总结(二十三)Scrapy中Download Middleware的用法
  • eclipse常用图标(类相关)及常用UML类图元素符号示意
  • dns相关
  • Netty(三) 什么是 TCP 拆、粘包?如何解决?
  • 简单理解js数据结构
  • js检测当前设备是移动端还是PC端
  • 开发者论坛一周精粹(第五十三期) ECS如何设置404页面? 首次WordPress建站大问题!...
  • linux必会10大排错命令
  • 小数据池
  • python程序员告诉你,python怎么学?30个特性带你快速了解python
  • 【391天】每日项目总结系列128(2018.03.03)
  • 2017-08-04 前端日报
  • Angularjs之国际化
  • CEF与代理
  • FastReport在线报表设计器工作原理
  • HTTP中的ETag在移动客户端的应用
  • iOS | NSProxy
  • Laravel 实践之路: 数据库迁移与数据填充
  • mysql innodb 索引使用指南
  • nginx 负载服务器优化
  • Redux 中间件分析
  • Spring Boot快速入门(一):Hello Spring Boot
  • 对JS继承的一点思考
  • 聚类分析——Kmeans
  • 小李飞刀:SQL题目刷起来!
  • 说说我为什么看好Spring Cloud Alibaba
  • ​520就是要宠粉,你的心头书我买单
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​Java并发新构件之Exchanger
  • # C++之functional库用法整理
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (+4)2.2UML建模图
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (2)STM32单片机上位机
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (arch)linux 转换文件编码格式
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .Net Core与存储过程(一)
  • .Net MVC4 上传大文件,并保存表单
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET/C# 使窗口永不获得焦点
  • .NET/C# 使用反射注册事件