JWT(Json Wen Token)原理剖析
JWT(即json web token),大家先看下面这张图

大家可以观察到,jwt String就是生成后的jwt字符集,其中有两个 "."(注意:jwt校验会对"."个数校验,多或少都会校验失败),被"."分割的就是jwt的三个构成部分,即:header、payload、sign。
接下来,给大家讲下jwt的生成规则和校验规则
JWT生成规则:
1、设置加密方式、claims信息(即payload)和signingkey
2、设置加密方式为header,并进行base编码
3、设置claims信息为payload,并进行base64编码
4、对header和payload用"."拼接成jwt,,使用signingkey按照加密方式进行加密,生成sign
5、对Jwt和sign用"."生成最终的jwt
JWT校验规则:
1、设置jwt和signingkey
2、按"."对jwt分成三部分,即:header、payload、sign
3、取第一部分进行base64解码,获取加密方式
4、取第二部分进行base64解码,获取业务参数,即payload
5、使用加密方式和signingkey创建校验器,对header+payload进行加密,并与sign(即第三部分)进行对比
6、取出payload的有效期进行校验,是否过期
7、通过校验,返回claims信息
附:
1、进行base64编码时,会判断是否为android客户端,使用base64的库不一样,这点可以自行看源码。
2、jwt会对生成的base64字符集的特殊符号进行转换,"-"换为"+",“_”换位"/",去掉尾部"="
3、jwt校验时,会判断是否有且只有两个".",否则校验失败
原理总结:
1、三部分里的header和payload是独立的,无须signingkey,只需base64解码即可看到payload的信息,所以千万不要在payload里放敏感信息
2、如果是使用jwt作为登录态校验,建议使用对称加密,因为非对称解密效率相对较慢,较多请求下会影响性能
3、因jwt是无状态的,之前见很多同学使用redis进行存储,我不是很明白,这岂不是违反了jwt当初的设计原则
4、保证密钥不要泄露,否则jwt可以被伪造
5、必要情况下,建议使用https
另附上个人的代码供大家参考
package com.yhc.demo.plugin; import java.io.UnsupportedEncodingException;
import java.util.Date; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException; /**
* JwtToken工具类
*/
@Configuration
public class JwtService { private static final Logger log = LoggerFactory.getLogger(JwtService.class); @Value("${jwt.secret:123456}")
private String secret;
@Value("${jwt.expiration:60}")
private Long expiration; /**
* 生成token
*
* @param username
* @return token
*/
public String generateToken(String username) { Claims claims = Jwts.claims();
claims.setIssuer(username); // jwt发行人
claims.setIssuedAt(new Date()); // jwt生成时间
claims.setExpiration(getExp()); // jwt过期时间
claims.setSubject("auth"); // jwt主题
claims.setAudience("yhc"); // jwt接受方
claims.setId("uuid"); // jwt唯一身份标识
claims.setNotBefore(new Date()); // jwt在此之前不可用 return generateToken(claims);
} /**
* 刷新token
*
* @param old token
* @return new token
*/
public String refreshToken(String token) {
Claims claims = validToken(token);
if (claims == null) {
return null;
}
claims.setIssuedAt(new Date());
claims.setExpiration(getExp());
return generateToken(claims);
} /**
* 根据token获取发行人
*
* @param token
* @return issuer
*/
public String getIssuer(String token) {
Claims claims = validToken(token);
return claims.getIssuer();
} /**
* 校验jwtToken,如无效,则返回Null,反之,返回负载对象
*/
private Claims validToken(String token) {
Claims claims = getClaimsFromToken(token);
if (claims != null) {
Date exp = claims.getExpiration();
if (exp.before(new Date())) {
log.warn("# jwtToken已失效:{}", token);
throw new RuntimeException("invalid token");
}
}
return claims;
} /**
* 从token中获取JWT中的负载参数
*/
private Claims getClaimsFromToken(String token) {
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
log.warn("# jwtToken格式验证失败:{}", token, e);
throw new RuntimeException("token verification failed");
}
return claims;
} /** 根据负载参数生成token */
private String generateToken(Claims claims) {
return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
} /** 获取token有效期 */
private Date getExp() {
return new Date(System.currentTimeMillis() + expiration * 1000);
} public static void main(String[] args) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException,
SignatureException, IllegalArgumentException, UnsupportedEncodingException { String username = "yhc"; Claims claims = Jwts.claims();
claims.setIssuer(username); // jwt发行人
claims.setIssuedAt(new Date()); // jwt生成时间
claims.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)); // jwt过期时间
claims.setSubject("test"); // jwt主题
claims.setAudience("yhc"); // jwt接受方
claims.setId("uuid"); // jwt唯一身份标识
// claims.setNotBefore(new Date()); // jwt在此之前不可用 String visitTK = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, "sad12f").compact();
System.out.println(visitTK);// SystemValue.JWT_HEADER_VALUE_PREFIX + Claims claimsDecode = Jwts.parser().setSigningKey("sad12f").parseClaimsJws(visitTK).getBody();
System.out.println(claimsDecode.getIssuer()); }
}
以上纯为个人总结,如有错误,还请指出,谢谢。
JWT(Json Wen Token)原理剖析的更多相关文章
- JWT(JSON Web Token)原理简介
原文:http://www.fengchang.cc/post/114 参考了一下这篇文章:https://medium.com/vandium-software/5-easy-steps-to-un ...
- Java JWT: JSON Web Token
Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...
- JWT(JSON Web Token) 【转载】
JWT(JSON Web Token) 什么叫JWTJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. 一般来说,互联网用户认证是这样子的. 1.用户向服务器发送用户名和密码. ...
- 5分钟搞懂:JWT(Json Web Token)
https://www.qikegu.com/easy-understanding/892 JWT 基于token的用户认证原理:让用户输入账号和密码,认证通过后获得一个token(令牌),在toke ...
- 温故知新,.Net Core遇见JWT(JSON Web Token)授权机制方案
什么是JWT JWT (JSON Web Token) 是一个开放标准,它定义了一种以紧凑和自包含的方法,用于在双方之间安全地传输编码为JSON对象的信息. 因此,简单来说,它是JSON格式的加密字符 ...
- 如何在SpringBoot中集成JWT(JSON Web Token)鉴权
这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...
- [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件
没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...
- ( 转 ) 什么是 JWT -- JSON WEB TOKEN
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...
- 关于JWT(Json Web Token)的思考及使用心得
什么是JWT? JWT(Json Web Token)是一个开放的数据交换验证标准rfc7519(php 后端实现JWT认证方法一般用来做轻量级的API鉴权.由于许多API接口设计是遵循无状态的(比如 ...
- 什么是JWT(Json Web Token)
什么是 JWT (Json Web Token) 用户认证是计算机安全领域一个永恒的热点话题. JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该to ...
随机推荐
- 深度学习基础入门篇[8]::计算机视觉与卷积神经网络、卷积模型CNN综述、池化讲解、CNN参数计算
深度学习基础入门篇[8]::计算机视觉与卷积神经网络.卷积模型CNN综述.池化讲解.CNN参数计算 1.计算机视觉与卷积神经网络 1.1计算机视觉综述 计算机视觉作为一门让机器学会如何去"看 ...
- C#识别文字内容并分类输出0和1
这个代码最开始是为了处理在调查问卷的结果,问卷星等调查问卷有一部分是用汉字描述的多选题,问卷系统在输出问卷的时候直接就是将汉字进行输出,而我们在进行数据分析(二元logistic或多项logistic ...
- 发布自己的项目到Maven中央仓库中
注册账号和生成GPG生成密钥教程 主要看注册账号和生成GPG密匙部分就行了,出现问题可以先在这两个地方找 gpg加密发布jar包到maven中央仓库详细过程以及踩的坑_佛系猿秦大昊的博客-CSDN博客 ...
- Dapr在Java中的实践 之 服务调用
服务调用 通过服务调用(Service-to-service Invocation),服务可以使用 gRPC 或 HTTP 这样的标准协议来发现并可靠地与其他服务通信. Dapr采用边车(Sideca ...
- 绘图;OSPF 虚连接
绘图;OSPF 虚连接 原图如下 绘图 实验拓扑 实验需求 按照图示分区域配置OSPF 配置虚连接认证 实验步骤 配置相应接口IP地址及loopback 环回口地址 按照图示分区域配置OSPF AR1 ...
- OSPF 多区域配置实验
实验拓扑 实验需求 按照图示配置 IP 地址和loopback 接口 按照图示分区域配置 OSPF ,实现全网互通 为了路由结构稳定,要求路由器使用环回口作为 Router-id 在AR3上配置静默接 ...
- 一篇文章带你入门HBase
本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 目录 HBase特性 Hadoop的限制 基本概念 NameSpace Table RowKey Column Time ...
- CoaXpress downlink数据解析方法
什么是downlink数据 downlink指的是相机传输到host采集卡的高速链路,其中包含了如下类型的数据: 1.Stream Data 2.Trigger Ack, Trigger: 3.Ack ...
- 从 SpringApplication 认识 Spring 应用启动过程
一.SpringApplication 是什么? Spring 应用的启动类. 二.SpringApplication 执行了什么? 创建 ApplicationContext 实例 Applicat ...
- 【Java学习】 Spring的基础理解 IOC、AOP以及事务
一.简介 官网: https://spring.io/projects/spring-framework#overview 官方下载工具: https://repo.spring.io ...