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)原理剖析的更多相关文章

  1. JWT(JSON Web Token)原理简介

    原文:http://www.fengchang.cc/post/114 参考了一下这篇文章:https://medium.com/vandium-software/5-easy-steps-to-un ...

  2. 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 ...

  3. JWT(JSON Web Token) 【转载】

    JWT(JSON Web Token) 什么叫JWTJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. 一般来说,互联网用户认证是这样子的. 1.用户向服务器发送用户名和密码. ...

  4. 5分钟搞懂:JWT(Json Web Token)

    https://www.qikegu.com/easy-understanding/892 JWT 基于token的用户认证原理:让用户输入账号和密码,认证通过后获得一个token(令牌),在toke ...

  5. 温故知新,.Net Core遇见JWT(JSON Web Token)授权机制方案

    什么是JWT JWT (JSON Web Token) 是一个开放标准,它定义了一种以紧凑和自包含的方法,用于在双方之间安全地传输编码为JSON对象的信息. 因此,简单来说,它是JSON格式的加密字符 ...

  6. 如何在SpringBoot中集成JWT(JSON Web Token)鉴权

    这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...

  7. [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件

    没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...

  8. ( 转 ) 什么是 JWT -- JSON WEB TOKEN

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...

  9. 关于JWT(Json Web Token)的思考及使用心得

    什么是JWT? JWT(Json Web Token)是一个开放的数据交换验证标准rfc7519(php 后端实现JWT认证方法一般用来做轻量级的API鉴权.由于许多API接口设计是遵循无状态的(比如 ...

  10. 什么是JWT(Json Web Token)

    什么是 JWT (Json Web Token) 用户认证是计算机安全领域一个永恒的热点话题. JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该to ...

随机推荐

  1. 深度学习基础入门篇[8]::计算机视觉与卷积神经网络、卷积模型CNN综述、池化讲解、CNN参数计算

    深度学习基础入门篇[8]::计算机视觉与卷积神经网络.卷积模型CNN综述.池化讲解.CNN参数计算 1.计算机视觉与卷积神经网络 1.1计算机视觉综述 计算机视觉作为一门让机器学会如何去"看 ...

  2. C#识别文字内容并分类输出0和1

    这个代码最开始是为了处理在调查问卷的结果,问卷星等调查问卷有一部分是用汉字描述的多选题,问卷系统在输出问卷的时候直接就是将汉字进行输出,而我们在进行数据分析(二元logistic或多项logistic ...

  3. 发布自己的项目到Maven中央仓库中

    注册账号和生成GPG生成密钥教程 主要看注册账号和生成GPG密匙部分就行了,出现问题可以先在这两个地方找 gpg加密发布jar包到maven中央仓库详细过程以及踩的坑_佛系猿秦大昊的博客-CSDN博客 ...

  4. Dapr在Java中的实践 之 服务调用

    服务调用 通过服务调用(Service-to-service Invocation),服务可以使用 gRPC 或 HTTP 这样的标准协议来发现并可靠地与其他服务通信. Dapr采用边车(Sideca ...

  5. 绘图;OSPF 虚连接

    绘图;OSPF 虚连接 原图如下 绘图 实验拓扑 实验需求 按照图示分区域配置OSPF 配置虚连接认证 实验步骤 配置相应接口IP地址及loopback 环回口地址 按照图示分区域配置OSPF AR1 ...

  6. OSPF 多区域配置实验

    实验拓扑 实验需求 按照图示配置 IP 地址和loopback 接口 按照图示分区域配置 OSPF ,实现全网互通 为了路由结构稳定,要求路由器使用环回口作为 Router-id 在AR3上配置静默接 ...

  7. 一篇文章带你入门HBase

    本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 目录 HBase特性 Hadoop的限制 基本概念 NameSpace Table RowKey Column Time ...

  8. CoaXpress downlink数据解析方法

    什么是downlink数据 downlink指的是相机传输到host采集卡的高速链路,其中包含了如下类型的数据: 1.Stream Data 2.Trigger Ack, Trigger: 3.Ack ...

  9. 从 SpringApplication 认识 Spring 应用启动过程

    一.SpringApplication 是什么? Spring 应用的启动类. 二.SpringApplication 执行了什么? 创建 ApplicationContext 实例 Applicat ...

  10. 【Java学习】 Spring的基础理解 IOC、AOP以及事务

    一.简介     官网: https://spring.io/projects/spring-framework#overview     官方下载工具: https://repo.spring.io ...