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());

}
}

以上纯为个人总结,如有错误,还请指出,谢谢。

(0)

相关推荐

  • Java,SpringBoot采用token方式实现登录认证

    IT小奋斗2021-01-13 21:48:33 Token,令牌,访问资源的凭证,每次访问带上这个令牌,就可识别出用户身份. JWT (JsonWebToken),是实现token技术的一种解决方案 ...

  • 2020前端开发者11个必备的网站

    网上有很多很棒的工具,让作为前端开发人员的我们生活的更加轻松.在这篇文章中,我将快速介绍一下我在开发工作中经常使用的11种工具. Node.green 用来查询当前 Node 版本是否某些功能.例如, ...

  • .NET Core 集成JWT认证

    JWT(Json web token)就不用过多的介绍了,在 .NET Core 开发中使用JWT进行认证也是比较常见的,而且接入过程也比较简单,随便配置配置就好了. 要想使用JWT,仅仅只需要在项目 ...

  • JWT-配置与使用

    JWT-配置与使用

  • Django REST Framework教程(7): 如何使用JWT认证(神文多图)

    在前面的DRF系列文章中,我们介绍了DRF认证(authentication)的本质, 以及自带的几种认证方案,包括TokenAuthentication方案.然而JSON Web Token(JWT ...

  • 第 82 天:Python Web 开发之 JWT 简介

    在之前的课程中,介绍过 Flask-Login 框架,它是基于 Session 和 Cookie 技术来实现用户授权和验证的,不过 Session 有很多的局限性,这一节介绍一种基于 token 的验 ...

  • 什么是 JWT -- JSON WEB TOKEN

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

  • Lightroom:校准面板工作原理剖析

    要了解 Lightroom 或 ACR 中的校准面板的工作原理,需要掌握原色通道的概念.互补色原理并能熟练使用 Ps 中的通道混合器命令. ◆  ◆  ◆ 校准面板的应用 校准面板中除了最上面的阴影滑 ...

  • 基于TL494 62.4V/10A充电机原理剖析

    W3使⑥脚电压为0.05V.   <<版权声明:本文由容源电子网(www.dziuu.com)整理提供,部分内容来源于网络,如有侵犯到你的权利请与我们联系更正.> 文中模块脚的编号次 ...

  • Java并发之AQS原理剖析

    优质文章,第一时间送达 作者 |  Yanci丶 来源 |  urlify.cn/IFJ3Mb 概述: AbstractQueuedSynchronizer,可以称为抽象队列同步器. AQS有独占模式 ...

  • Imfile背后的技术原理剖析

    近期出现了FIL,XCH,BZZ这些存储系统出来,好多人都不了解就拼命的冲进去,一起狂欢,最后落得一地鸡毛,其实分布式存储要落地到民众使用太难,本次我们讲解下最接地气的比特流(Bittorrent)技 ...

  • 汽车变速器结构原理剖析

    变速器是用来改变来自发动机的转速和转矩的机构,它能固定或分档改变输出轴和输入轴传动比,又称变速箱.变速器由变速传动机构和操纵机构组成,有些汽车还有动力输出机构.传动机构大多用普通齿轮传动,也有的用行星 ...

  • 汉字特的造字原理剖析

    我们先来看看<说文>的解释, 特,朴特,牛父也.--<说文> 什么意思呢?许慎这样解释其实就等于没解释.也就是有个最先养牛的人,叫做朴特.所以特字是什么意思?指最先养牛那个人? ...

  • 万能腰痛法:腰部六点法与其原理剖析

    腰痛是临床上的常见症状,患者可能由于肌肉.神经.小关节紊乱.椎间盘突出等原因,医生需要详细评估,找到靶点,然后才去处理.但是很多时候处理后效果依然不明显,打击个人信心不说,且对评估产生怀疑.正如我在第 ...

  • 【笔法】屋漏痕•折钗股•锥划沙——原理剖析 图字互证 用笔示范

    "蓝色字" 弘扬鲁公文化   传承颜体书法 经常听到一些书家前辈讲笔法时说到"屋漏痕"."折钗股"和"锥划沙",感觉很生 ...