当前位置: 首页 > 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
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【翻译】babel对TC39装饰器草案的实现
  • Android框架之Volley
  • in typeof instanceof ===这些运算符有什么作用
  • isset在php5.6-和php7.0+的一些差异
  • quasar-framework cnodejs社区
  • Shell编程
  • spring-boot List转Page
  • Sublime Text 2/3 绑定Eclipse快捷键
  • Vue ES6 Jade Scss Webpack Gulp
  • 彻底搞懂浏览器Event-loop
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 构造函数(constructor)与原型链(prototype)关系
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 那些被忽略的 JavaScript 数组方法细节
  • 你不可错过的前端面试题(一)
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 小程序01:wepy框架整合iview webapp UI
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​queue --- 一个同步的队列类​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #mysql 8.0 踩坑日记
  • (0)Nginx 功能特性
  • (C语言)字符分类函数
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (ZT)薛涌:谈贫说富
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (三分钟)速览传统边缘检测算子
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .Net Remoting常用部署结构
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .NET中两种OCR方式对比
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限