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

json web token 网上学习笔记

JSON Web Token(JWT) - 实现系统集成授权访问


这是一个第三方系统访问AnyReport报表系统使用JWT授权的实现案例,AnyReport报表系统暴露报表资源URL供第三方系统访问,
第三方系统可以使用iframe,src设置为报表链接访问报表资源,这时资源URL类似restful api需要被认证的系统才能访问,
通过JWT的好处是不需要做登录认证在服务器端建立session。

JWT组成部分

JSON web Token 简称JWT,是一种token的URL安全方法,用于在网络通信的双方之间传递
JWT传输内容是由头部 header、负载 payload、签名 signature 三部分组成
header 定义Token 类型、加密类型,告诉服务器端使用的加密方法是HmacSHA256(HS256)

 

1
2
3
4
{
   "typ" : "JWT" ,
   "alg" : "HS256"
}

负载 payload 定义一些需要使用的信息:客户端ID、JWT创建的时间、用户ID,负载中不需要传输敏感信息如密码、密钥等,JWT内容通过HTTP传输不安全。

1
2
3
4
5
{
   "cid" : "OA0001" ,
   "iat" : 1482656248798,
   "uid" : "admin"
}

cid:是第三方系统的标示,因为可能多个第三方系统访问报表系统,报表系统可以根据cid查询密钥、失效时间等做JWT内容验证。
iat:创建JWT的时间,服务器端根据该iat判断JWT是否已经失效了,防止链接被别人获取。
uid:用户ID,服务器端可以根据该用户查询一些用户相关的信息,如一些权限信息,这个案例并没有使用这个字段。

签名 signature 部分是使用密钥对header Base64与payload Base64加密的Base64字符串。
JWT三个部分使用“.”链接的字符串, 最终JWT是:header base64字符串 + payload base64 字符串 + HmacSHA256(headerBase64 + "." + payloadBase64) base64字符串

1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjaWQiOiJPQTAwMDEiLCJpYXQiOjE0ODI2NTcyODQyMjF9.TeJpy936w610Vrrm+c3+RXouCA9k1AX0Bk8qURkYkdo=

JWT生成方法

JWT是由第三方系统生成的,可以使用服务器端语言,也可以使用Javascript生成,这种方式是最简单的,密钥保存在第三方系统服务器端当进入页面可以将密钥给js, js获取密钥而生成JWT,这里第三方系统密钥与报表系统密钥一致,各保留一份无需传输。

1
2
3
4
5
6
7
8
9
10
11
12
13
function token() {
     var base64 = new Base64(); //网上寻找一个base64库
     var header= '{"typ":"JWT","alg":"HS256"}' ;
     var headerBase64 = base64.encode(header); //header base64字符串
     var date = new Date();
     var payload = '{"cid" : "OA0001","iat" : 1482656248798,"uid" : "admin"}' ;
     var payloadBase64 = base64.encode(payload); //payload base64字符串
     var base64Token = headerBase64 + "." + payloadBase64;
     var signature = CryptoJS.HmacSHA256(base64Token, "123456" ); //使用google的hmac-sha256.js库
     var signatureBase64 = base64.hex2b64(signature.toString());
     var jwt = base64Token + "." + signatureBase64;
     return jwt;
}

生成的base64的token作为URL请求资源,url还需要做urlencoding编码

1
2
//url?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjaWQiOiJPQTAwMDEiLCJpYXQiOjE0ODI2NTcyODQyMjF9.TeJpy936w610Vrrm%2Bc3%2BRXouCA9k1AX0Bk8qURkYkdo%3D
url?jwt=encodeURIComponent(token());

JWT验证

验证是在报表系统服务器端进行,验证部分比较简单的,采用Java解析JWT并做验证, 首选将jwt按“.“分割为parts三部分header,payload、signature, 使用js相同的密钥如“123456”进行加密,得到加密结果与jwt的signature进行比较,如果相等表示验证通过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static boolean verify(String jwt) {
     String[] parts = jwt.split( "\\." );
     String payload = StringUtils.newStringUtf8(Base64.decodeBase64(parts[ 1 ]));
     JSONObject json = JSONObject.fromObject(payload);
     String clientId = json.getString( "cid" );
     long iatTime = json.getLong( "iat" );
     //验证jwt是否失效
     if (System.currentTimeMillis() - iatTime > 3600 * 1000 ) {
         return false ;
     }
     //验证签名 signature
     byte [] content = (parts[ 0 ] + "." +  parts[ 1 ]).getBytes(StandardCharsets.UTF_8);
     byte [] signature = Base64.decodeBase64(parts[ 2 ]);
     try {
         return verifySignatureFor( "HmacSHA256" , "123456" , content, signature);
     } catch (Exception e) {
         throw new RuntimeException(e);
     }
 
}
 
public static boolean verifySignatureFor(String algorithm,  String secret, byte [] contentBytes, byte [] signatureBytes) throws Exception {
     byte [] secretBytes = secret.getBytes(StandardCharsets.UTF_8);
     Mac mac = Mac.getInstance(algorithm);
     mac.init( new SecretKeySpec(secretBytes, algorithm));
     return MessageDigest.isEqual(mac.doFinal(contentBytes), signatureBytes);
}

转载于:https://www.cnblogs.com/chongchong0207/p/7403612.html

相关文章:

  • python中函数包括_python函数
  • bzoj1059 [ZJOI2007]矩阵游戏
  • python 直方图的绘制方法全解_python可视化:matplotlib绘制直方图进阶篇!
  • CPU位数、操作系统位数、机器字长、C/C++基本数据类型长度
  • python决策树分类 导入数据集_python中使用scikit-learn和pandas决策树进行iris鸢尾花数据分类建模...
  • 2017/08/22 工作日志
  • 为什么安装了python桌面没有图标_python-pyinstaller不显示图像和图标
  • MySQL Workbench出现:Error Code: 2013. Lost connection to MySQL server during query的问题解决...
  • python运行无响应_python tkinter窗口无响应
  • Ubuntu 报错 sudo: unable to resolve host
  • rtmp推流软件_八爪龙多路直播--导播台推流
  • springboot + swagger2 学习笔记
  • 项目背景怎么描述_没关系、没背景怎么接项目?记住这三点,中标率提高80%
  • SQL 笔记1,left join,group by,having
  • asp.net添加删除表格_Excel你还在手动加边框线?太麻烦!一招教你让它自动添加和删除...
  • Android组件 - 收藏集 - 掘金
  • canvas 五子棋游戏
  • Debian下无root权限使用Python访问Oracle
  • Javascript弹出层-初探
  • Java小白进阶笔记(3)-初级面向对象
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • PHP 7 修改了什么呢 -- 2
  • php中curl和soap方式请求服务超时问题
  • Python进阶细节
  • SQLServer之创建数据库快照
  • 浮现式设计
  • 解决iview多表头动态更改列元素发生的错误
  • 那些被忽略的 JavaScript 数组方法细节
  • 前端技术周刊 2019-02-11 Serverless
  • 如何在 Tornado 中实现 Middleware
  • 网页视频流m3u8/ts视频下载
  • 怎么将电脑中的声音录制成WAV格式
  • 栈实现走出迷宫(C++)
  • - 转 Ext2.0 form使用实例
  • ![CDATA[ ]] 是什么东东
  • (3)nginx 配置(nginx.conf)
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (数据结构)顺序表的定义
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)负载均衡,回话保持,cookie
  • (转载)Linux网络编程入门
  • .Family_物联网
  • .md即markdown文件的基本常用编写语法
  • .net CHARTING图表控件下载地址
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .net 托管代码与非托管代码
  • .NET成年了,然后呢?
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理