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. GitLib详细使用手册(windows系统)

    Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. 对gitlab的常见的使用有建立仓库.提交代码.更新代码.回滚代码.显示/修改日志.拉取分支.解决冲突.设置比 ...

  2. SpringIOC个人笔记

    上一章讲解了SpringBoot中的 AutoConfiguration自动装配,而这一章就来讲讲自动装配时会用到的Spring三大特性之一的IOC控制反转. ​ 使用过Spring的人都熟知,Spr ...

  3. js代理(Proxy) 和 反射(Reflection)

    在实际开发中经常会遇到js抛出的错误,但是我们有没有想过自己去接管js异常验证,根据自己的需求抛出异常呢?原本也许不行,但是在es6出来后就可以做到了 一.代理(Proxy) 什么是'代理' 呢?代理 ...

  4. Kubernetes(k8s)定时任务:CronJob

    目录 一.系统环境 二.前言 三.Kubernetes CronJob简介 四.kubernetes CronJob和Linux crontab对比 五.CronJob表达式语法 六.创建CronJo ...

  5. 一次 SSH 攻击与处理小记

    这是我在简书看到的一个作者经历,结合小编自己的一些实践,抛砖引玉,给大家分享一下. 有段时间发现集群异常卡顿.担心的事情终于发生了,使用命令 lastb 查看了一下,我的天呢,好多未知的 IP,我随便 ...

  6. OpenSSL 是什么?

    OpenSSL 是什么? OpenSSL 是开源的程序套件,该套件由三部分组成: libcrypto:具有通用功能的加密库,里面包含众多加密算法 libssl:实现 SSL/TLS 功能 openss ...

  7. 【后端面经-数据库】MySQL的存储引擎简介

    目录 MySQL的存储引擎 0. 存储引擎的查看和修改 1. MyISAM 2. InnoDB 3. MEMORY 4. MERGE 5. 总结 6. 参考博客 MySQL的存储引擎 mysql主要有 ...

  8. 如何在Databricks中使用Spark进行数据处理与分析

    目录 <如何在Databricks中使用Spark进行数据处理与分析> 随着大数据时代的到来,数据处理与分析变得越来越重要.在数据处理与分析过程中,数据的存储.处理.分析和展示是不可或缺的 ...

  9. OOP4-6题目集总结

    4-6次题目集,从集合框架,正则表达式,类的继承与多态三个方面展开,在帮助我们了解java常用的工具(集合框架,正则表达式)的同时让我们学着利用类与类之间的关系来减少耦合,第六次题目集侧重于类的继承与 ...

  10. springboot下拦截器的单例模式写法

    最近在学习springboot的时候,要把用户登录的做一个拦截,又想到了不采用new对象方式,于是想到使用单例模式来进行构造拦截器对象,所以下面看代码. (不知道这个是不是要写成单例模式,也许是我最近 ...