手写jwt验证,实现java和node无缝切换
前言
前端时间和我朋友写了一个简易用户管理后台,功能其实很简单,涉及到的技术栈有:vue+elementUI,java+spring MVC以及node+egg,数据库用的mysql,简单方便。
一开始是我是只负责前端,但是前端开发的的速度太快,老是没事,加上他小子并没有接触过实战的项目,又怕他出乱子,所以考虑我也写一个后端,
开始考虑的是用python+django,但是还是在半途放弃了,因为总感觉Django不过灵活,使用起来非常别扭,也可能是用scrapy写爬虫写多了,难以理解django的框架设计,总是会把他想象成一个scrapy架构,也导致代码写的很乱,下面上一张scrapy架构图。

所以最后考虑的用node,Express和Koa框架学习过node应该都知道,我以前也用过express(写过一个小demo),但是给我的感觉这到像是一个只能有5年以上node开发经验才能玩的转的,因为express是非常的精简的,安装它后,会发现它几乎不会为你提供任何编码规范,也没有约束你的框架应该怎么设计,以至于新手下载完成后完全不知道自己应该干嘛,甚至不知道直接的文件应该写在哪,没有框架本身的约定,标准的MVC模型有着千奇百怪的写法,所以我觉得没有一定的架构思想和经验是很难驾驭的。
koa我并没有直接的使用过,只是听说是express的原班人马打造的,中间件是基于洋葱圈模型实现的。下面上一张图洋葱圈模型图。

而是后来直接就接触的egg,egg标语是“为企业级框架和应用而生”,通道
废话说的有点多了,重点是通一套前端代码,开发了两套后端代码,功能是完全一致的,后端都实现了相应的jwt验证功能,-->json web token,密钥都是我们约定好的固定值,但是最后发现一样的密钥,相同的数据,使用的jwt包不同产生的结果也不同,这也就导致两端之间无法相互切换,每次切换必须从登陆重新开始,这不太符合逻辑,而且重要的是后面的安排有需要这样的功能,无法做到无缝切换就直接导致实现不了下面的功能。
提纲内容
- jwt实现原理
- jwt未能解决的疑惑
- base64和base64url
jwt实现原理
其实作为一个前端开发人员,jwt实现原理我是没必要懂得的,但是如果你不限于此,这算是个必不可少的内容了吧。
先上一张图。

图中数字1是后端使用jwt工具包生成的token,通常是由三部分组成,也就是token中间的两个“.”将其分为三部分,第一部分对应的是右边的数字2部分,然后依次对应。
这三部分分别是头部、有效载荷、签名。
头部:alg是指说用到的算法,type当然是令牌类型
有效荷载:sub所签发的用户,name是签发者的姓名,lat是这签发时间,exp是指到期时间,当然还有一些其他的,这些数据都是非必要数据,实则只有exp可能有用,因为有效数据实际都是在data里面,当然你也可以不这么做。
签名:前两者都是通过base64url编码过的,而非是算法加密的,所以几乎是透明的。但是签名是默认是通过hsa256算法加密的 ,加密的规则是:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
如何验证token呢?那更加简单了,就是用前端传回来的token前两部分和服务器存的秘钥再次加密一次,然后做base64url处理和第三部分比较,一样代表这个token是自己签发的,不一样代表是伪造的,完了过后再将有效载荷部分进行base64url反编码,就得到exp,然后和当前时间比较是否过期。
jwt未能解决的疑惑
经过测试,发现三个问题。
1、 node和java使用对应的jwt工具包生成的token不相同,这里是指在一系列参数完全相同的情况下。
2、 还发现用java生成的token在jwt官网解析时候输入秘钥结果的到的签名和自己的签名不一样,但是node是一样的,于是就产生了java工具包在输入签名的时候对密钥进行了其他处理的想法,但是他并没有找出做出来怎么样的处理,也就是说我们在生成签名的时候根本就连密钥都是不一样的。
3、 不管是node还是java生成的token,我们用原来一模一样的数据和一样的算法公式都产生不了和工具包生成一样的签名,也就是可以怀疑在进行hsa256算法加密前确实对秘钥进行处理了。
base64和base64url
base64就是一种二进制编码方式,原理很简单,先准备一个包含64个字符的数组:
['A','B','C',...'a','b','c',...'0','1','2',...'+','/']
然后对二进制数据进行处理,每三个字节一组,一共24bit,一个字节8bit嘛,然后再将24分为4组,每组正好6bit。6bit的话就刚好能表示64个字符。如果编码字符不是3的倍数,就会剩下一个字节或者两个字节,这个时候就在后面填充\x00,再在编码末尾加上一个或者两个=号。解码的时候制动力去掉就好了。
base64url编码就是将字符编码成url能传递的参数,因为base64编码会出现+号和/号,然后就会在url中出现问题,所以base64url其实就是将+和/分别变成-和_
手写jwt验证,实现java和node无缝切换的更多相关文章
- 算法是什么(二)手写个链表(java)
算法是什么(二)手写个链表(java) liuyuhang原创,未经允许禁止转载 目录 算法是什么(〇) 很多语言的API中都提供了链表实现,或者扩展库中实现了链表. 但是更多的情况下,Map(或 ...
- 手写代码注意点--java.lang.Math 相关
1-如果用到了Math的函数,需要手动写上: import java.lang.Math; 2-求x的y次方,用的是Math.pow(x,y); 注意,返回值是double!!! 不是int, 如果需 ...
- 手写代码注意点--java.util.Stack相关
1-Stack的基本函数为: 注意: 取栈顶的函数为peek(),不是top()... 测试stack是否为空的函数为empty(),不是isEmpty()...
- java 从零开始手写 RPC (07)-timeout 超时处理
<过时不候> 最漫长的莫过于等待 我们不可能永远等一个人 就像请求 永远等待响应 超时处理 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RP ...
- 2 手写Java LinkedList核心源码
上一章我们手写了ArrayList的核心源码,ArrayList底层是用了一个数组来保存数据,数组保存数据的优点就是查找效率高,但是删除效率特别低,最坏的情况下需要移动所有的元素.在查找需求比较重要的 ...
- 阿里第二轮面试:手写Java二叉树
阿里面试 现在很多公司在招聘开发岗位的时候,都会事先在招聘信息中注明面试者应当具备的知识技能,而且在面试的过程中,有部分对于技能掌握程度有严格要求的公司还会要求面试者手写代码,这个环节很考验面试者的基 ...
- 教你如何使用Java手写一个基于链表的队列
在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...
- 6 手写Java LinkedHashMap 核心源码
概述 LinkedHashMap是Java中常用的数据结构之一,安卓中的LruCache缓存,底层使用的就是LinkedHashMap,LRU(Least Recently Used)算法,即最近最少 ...
- 使用java语言基于SMTP协议手写邮件客户端
使用java语言基于SMTP协议手写邮件客户端 1. 说明 电子邮件是互联网上常见的应用,他是互联网早期的产品,直至今日依然受到广大用户的喜爱(在中国可能因为文化背景不同,电子邮件只在办公的时候常用) ...
随机推荐
- uniapp 与C# 加解密
1 uni-app操作 (1) 打开HBuilderX的视图->显示终端 cd 切换到你项目的根目录 执行命令 npm install crypto-js 安装成功后你的项目根目录会生成node ...
- 再谈Transaction——MySQL事务处理分析
MySQL 事务基础概念/Definition of Transaction 事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个 sql 语句,这些语句要么都执行 ...
- django2.0+连接mysql数据库迁移时候报错
django2.0+连接mysql数据库迁移时候报错 情况一 错误信息 django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 ...
- DRF框架中csrf异常
一.报错信息 "detail": "CSRF Failed: CSRF cookie not set." 二.解决办法 方法一: 在配置文件中配置 REST_F ...
- [BZOJ1833][ZJOI2010]数字计数
Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文 ...
- Cocos2d-x 学习笔记(26) 从源码学习 DrawCall 的降低方法
[Cocos2d-x]学习笔记目录 本文链接:https://www.cnblogs.com/deepcho/cocos2dx-drawcall-glcalls 1. 屏幕左下角 我们通常在Cocos ...
- 一起来看一下Java中的Annotation注解
目录: 一. 什么是Annotation 二. Annotation的作用 2.1 编译器使用到的注解 2.2 .class文件使用到的注解 2.3 运行期读取的注解 三. 定义Annotation ...
- Hello World ! 节日快乐!
节日快乐! 世界你好,Hello World Java public class HelloWorld{ public static void main(String[] args) { System ...
- i春秋DMZ大型靶场实验(三)内网转发DMZ2
更具实验文件知道存在源码泄露 下载源码进行源码审计 发现admin账号 查看user.php 发现mysql 账号 端口 对登录后源码进行审计 发现上传文件的两处漏洞 对 fiel name 可以 ...
- Java类型信息(RTTI和反射)
要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人! 最近在学习反射,为了更好地理解反射,就 ...