Java - JWT的简单介绍和使用

  • 前言
  • 一. JWT 基础知识
    • 1.1 session 案例测试
    • 1.2 JWT 结构
      • 1.2.1 Header
      • 1.2.2 Payload
      • 1.2.3 Signature ☆
  • 二. JWT 简单使用
    • 2.1 生成JWT
    • 2.2 解析JWT
    • 2.3 常见的异常

前言

目前自己在做一个云直播个人项目,后端架构是微服务,目前准备用JWT来做Token的校验。借此机会来复习和学习一遍JWT的相关知识。

一. JWT 基础知识

JWT的全称是JSON Web Tokens主要是服务器认证相关信息之后,生成一种JSON数据,并通过一种算法(例如HMAC)对其进行安全的签名加密。主要用于两个用途:

  • 数据交换:因为JWT使用JSON来存储相关数据,而JSON这一种数据格式可以在各方之间传递。
  • 安全验证:登录之后,后续的请求可以携带JWT,只有携带了JWT(认证Token)的请求才能够正常地访问到相关的数据及资源。

一般我们在开发过程中,凡是涉及到用户登录的,我们就需要去考虑用什么去存储用户登录的一个状态,本文只说两种:

  • session(基于cookie的实现):只不过session相关的数据存储于服务器。
  • JWT:一旦生成,一般就抛给客户端去保存。客户端只需要每次携带这个Token就可以正常地访问接口。

1.1 session 案例测试

我们来写一个简单的案例:pom依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version>
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

Controller代码:

@RestController
public class UserController {@GetMapping("/login")public String login(HttpServletRequest request) {request.getSession().setAttribute("user", "Ljj");return "Login Success";}@GetMapping("/getUser")public String getUser(HttpServletRequest request) {String user = (String) request.getSession().getAttribute("user");return user;}
}

那么我们项目启动之后,访问以下路径:http://localhost:8080/login,就能发现当前客户端会多出一个名为JSESSIONIDCookie

之后我们的每一次请求,都会自动携带上这个cookie去访问服务端:

如果我们采取session来存储用户信息,那么大致流程就是如下:

  1. 用户登录成功,那么我们就request.getSession().setAttribute("user"+userId, "用户信息")
  2. 此时服务端就会写入一个session来保存相关的数据(基于cookie实现)。因此客户端能看到一个名为JSESSIONIDCookie
  3. 后续的相关请求,都会自动携带这个Cookie,后端就可以取到这个用户信息了。

但是,采用session这种方式,是以本地缓存来存储相关的数据的,当有100个用户进行登录的时候,就需要在本地缓存存储100个信息。因此会给服务器带来一定的内存压力。

相关的数据存储于StandardSession.attributes字段中:

public class StandardSession implements HttpSession, Session, Serializable {protected ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
}

因此现在主流的都是使用JWT来代替传统的session存储方案。

1.2 JWT 结构

JWT如上文所说,他是一个JSON串,但是它有着自己的特定结构:

Header.Payload.Signature

HeaderPayload部分都是一个base64编码串,三个结构之间通过 ” . “ 进行连接。

1.2.1 Header

Header头部,通常有两个部分组成:

  • alg:表示签名的算法类型,比如HMAC SHA256 或者 RSA
  • typ:代表这个token令牌的类型,比如JWT

案例如下:

{"alg": "HS256","typ": "JWT"
}

最后这个JSON串会通过Base64Url进行编码,然后作为JWT的第一部分。

1.2.2 Payload

JWT的第二部分就是这个Payload了,它的中文含义叫做:有效载荷。相当于我们HTTP请求的一个请求体了。一般用来存储我们实际要传递的数据。例如:

{"sub": "1234567890","name": "John Doe","admin": true
}

Payload本身还规定了几个属性,同时它可以分为三种类型:

标准注册声明:

  • iss (issuer):签发人。
  • exp (expiration time):过期时间。
  • sub (subject):主题。
  • aud (audience):接收方。
  • nbf (not before):生效时间。
  • iat (issued at):签发时间。
  • jti (jwt id):编号。

公共声明: 一般用于我们自己定义一些业务属性。


私有声明: 服务器和客户端共同定义的声明

这一部分的内容可见比较丰富,因为我们可以将自定义的属性塞进去,但是有一点我们需要格外地注意:Payload部分不建议添加敏感信息,例如密码、身份证等信息。因为Payload这一部分最终也是经过Base64Url进行编码,然后作为JWT的第二部分暴露给客户端。因此这个是可以被解码的。

1.2.3 Signature ☆

上面的两个JWT组成部分:HeaderPayload,我们知道它是由Base64Url进行编码的,那么自然而然的它就可以被解码。那么JWT的安全性谈何而来?这就得看最后一个部分Signature签名了。他的作用一句话概括就是:对前两部分的内容进行算法签名,防止数据篡改。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)

这个代码是啥意思呢?

  1. 拿到经过Base64编码的HeaderPayload部分。以及我们自己提供的一个秘钥secret
  2. 使用Header中指定的签名算法:HMAC SHA256 进行签名。

签名的目的:

  1. 如果有人对头部以负载内容进行解码,然后篡改相关信息,在进行base64编码重新组合一个新的JWT
  2. 那么这个JWT传输给服务器后,服务器能够判断,新的头部和新的负载内容形成的签名和原有的不一致。
  3. 那么此时就能够判断这个JWT是不合法的。因为外部使用者无法得知你进行签名时的秘钥是什么。 因此通过修改JWT算出来签名是不一样的。

那么最后再来说下JWT的特点:

  • JWT的两个组成部分虽然是经过base64编码的,因此他可以被解码。但是JWT本身是可以被加密的。这样就更加安全。
  • JWT生成之后,不必存储在服务器端,就没有使用session存储那样,有着内存压力。
  • JWT 无法使服务器保存会话状态,当令牌生成后在有效期内无法取消也不能更改。
  • 安全:因为Token不是Cookie。我们只需要每次请求的时候携带Token即可。由于没有Cookie被发送,还有助于防止CSRF攻击。
  • 不要再JWT中存储一些敏感信息,一般都是存储userId

二. JWT 简单使用

首先准备pom依赖:

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.19.1</version>
</dependency>

2.1 生成JWT

public class JwtTest {// 秘钥,你可以随便取,可以取的难一点public static final String SECRET = "ASD!@#F^%A";@Testpublic void testTokenCreate() {HashMap<String, Object> headers = new HashMap<>();// 过期时间,60sCalendar expires = Calendar.getInstance();expires.add(Calendar.SECOND, 600);String jwtToken = JWT.create()// 第一部分Header.withHeader(headers)// 第二部分Payload.withClaim("userId", 20).withClaim("userName", "LJJ").withExpiresAt(expires.getTime())// 第三部分Signature.sign(Algorithm.HMAC256(SECRET));System.out.println(jwtToken);}
}

结果如下:看红圈的两个"."符号,可见JWT的格式和第一章节描述的相吻合。

那么拿到令牌了,我们接下来就是根据令牌去解析数据。

2.2 解析JWT

注意:这里你要把2.1节生成的token自己复制一下,贴到代码里面。

@Test
public void testReadJWT() {// 创建一个验证的对象JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6IkxKSiIsImV4cCI6MTY2NzcyMTMzMiwidXNlcklkIjoyMH0.AJA88B0F-zKEJUCIGp9kSx2TlbpoyH88GzEn-9xN5XI");System.out.println(verify.getClaim("userId").asInt());System.out.println(verify.getClaim("userName").asString());System.out.println("过期时间:" + verify.getExpiresAt());
}

结果如下:

2.3 常见的异常

这里贴出4个常见的异常,如果JWT校验不通过,就会抛出异常:

  • SignatureVerificationException:签名不一致。
  • TokenExpiredException:令牌过期。
  • AlgorithmMismatchException:算法不匹配异常。
  • InvalidClaimException:失效的Payload异常。一般存在于这种情况:获取token的服务器比使用token的服务器时钟快,请求分发到时间慢的服务器上导致token还没生效。

Java - JWT的简单介绍和使用相关推荐

  1. 【软件开发】Java语言的简单介绍

    Java语言的简单介绍 一.Java语言的介绍 二.Java的版本 三.JDK的介绍 四.Java API文档 五.Java语言的特点 1. 面向对象 2. 解释性 3. 多线程 4. 可移植性 / ...

  2. java同步机制简单介绍

    在java编程里经常听到类似的术语: 这个函数是不是同步的... 本文就简单介绍下什么是同步, java中同步的一些处理方法. 1.同步问题产生的原因 Java中同步问题是伴随这多线程而产生的, 也就 ...

  3. Java基础-web简单介绍

    web简单介绍 什么是Web? 什么是Java web? 使用Java语言进行开发. 软件架构: CS结构的软件:  CS:Client/Server客户端和服务器,这种软件往往需要安装.比如QQ,迅 ...

  4. Java之GUI简单介绍

    GUI介绍(一)常见的组件及简单监听器 第一个窗口程序 容器控件 JLabel控件 简单事件处理 文本框JTextFiled 复选框JCheckBox 下拉列表JComboBox 布局管理器Layou ...

  5. Java 多态的简单介绍.

    作为面向对象三大知识点之一,  多态可以讲是相对最难理解那个. 本人在这里也是简单分析一下. 一, 多态的定义. 面向对象编程中, 1个超类的引用可以指向属于超类的对象, 也可以根据需要指向超类的派生 ...

  6. linux java jar war_简单介绍Java 的JAR包、EAR包、WAR包区别

    WAR包 WAR(Web Archive file)网络应用程序文件,是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件.War专用于Web方面.大部分的JAVA WEB工程,都是打成WAR包 ...

  7. Java多态(简单介绍)

    多态是Java面向对象的一个重要特征.多态就是不同的对象对同一个事物做出的不同反应.方法重写是实现多态的基础. 1.向上转型 父类引用指向子类 向上转型的语法: <父类型> <引用变 ...

  8. Java基础—反射—简单介绍

    一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见的 JavaScript 就是动态语言,除此之外 Ruby,Python 等也属于 ...

  9. java.util.Scanner简单介绍

    当想要接收用户从键盘输入的信息时,就要使用Scanner类. 基本使用方法: import java.util.Scanner;public class Test02 {public static v ...

最新文章

  1. js-new、object.create、bind的模拟实现【转载备忘】
  2. 用友致远协同OA办公软件可以给外驻领导带来什么好处?
  3. pycharm pycharm中用matplolib的ax3.plot_surface画出的3D(三维图)(三维函数)不能旋转怎么办?
  4. rola物联网框架_如何搭建一个物联网系统框架?
  5. Bootstrap组件_导航
  6. How is JerryMaster.view.xml being loaded in WebIDE local test environment
  7. node --- 后端使用bcrypt对密码进行加密处理
  8. Linux Shell脚本入门教程系列之(七)Shell输出
  9. 使用base64编码把背景添加到CSS文件中
  10. 计算一个文件下的所有视频总时长
  11. python调用darknet
  12. 2022年中国游戏行业投融资发展报告
  13. Windows下TexLive2015 TeXstudio 和SumatraPDF安装配置
  14. 『伪原创工具 』英文在线伪原创工具
  15. 河南高二计算机会考excel,(完整版)高中信息技术学业水平考试Word、Excel操作题考点总结...
  16. 计算机网络中属于通信子网,计算机网络通常被划分为通信子网和资源子网,通信子网提供信息传输服务,资源子网提供共享资源。...
  17. 共享黑名单是行业潜规则
  18. 【EXCEL】去除多余行列
  19. swift网络请求封装(Moya)
  20. php unlink没有权限,php中删除文件用unlink函数权限判断_PHP教程

热门文章

  1. recaptcha java_reCAPTCHA打不开的解决方法
  2. Mac 下百度网盘如何进行加速? 使用Aria2GUI
  3. aarch64安装numba
  4. uniapp 商城实例
  5. 使用shell下载查找对应的电影
  6. Google怎么赚钱(转)
  7. 小程序怎么开通流量主
  8. vue cli3 添加 px2rem-loader
  9. 【读书心得】《格局》吴军
  10. 【Android进阶】天天动听 悬浮歌词(迷你歌词)效果解读