SpringBoot - 集成Auth0 JWT
前言
说说JWT,先说下互联网服务常见的两种用户认证方式:
session认证与Token认证
session认证
传统的Session认证的大体流程可以表示为用户提供用户名和密码登录后由服务器存储一份用户登录信息并传递给浏览器保存为Cookie,并在下次请求中根据Cookie来识别用户,但这种方式缺陷明显:
- Session都是保存在内存中,随着认证用户的增多,服务端的开销明显增大
- 保存在内存中的Session限制了分布式的应用
- Cookie容易被截获伪造
Token认证
Token 泛指身份验证时使用的令牌,Token鉴权机制从某些角度而言与Cookie是一个作用,其目的是让后台知道请求是来自于受信的客户端,其通过实现了某种算法加密的Token字符串来完成鉴权工作,其优点在于:
- 服务器不需要保存 Session 数据(无状态),容易实现扩展
- 有效避免Cookie被截获引发的CSRF攻击
- 可以存储一些业务逻辑所必要的非敏感信息
- 便于传输,其构成非常简单,字节占用小
JWT简介
JWT定义
- JWT全称为Json web token,也就是 Json 格式的 web token,可以这么理解:
Token // 个人证件
JWT // 个人身份证
JWT数据结构
- JWT由三段字符串组成,中间用.分隔,如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjEsInNjb3BlIjo4LCJleHAiOjE3MTU3NDAyMjIsImlhdCI6MTYyOTM0MDIyMn0.wuRsF5wvLHbDF_21Pocas8SeXQ315rgBl6wm1LRL2bQ
- JWT 的三个部分依次如下:
Header(头部)// Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。
Payload(负载)// Payload 部分是一个 JSON 对象,用来存放实际需要传递的数据
Signature(签名)// Signature 部分是对前两部分的签名,防止数据篡改
- 第一段字符串Header:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
将其 Base64 解码后得到:
{
"typ": "JWT", // TOKEN TYPE ,token类型
"alg": "HS256" //ALGORITHM,算法 哈希256
}
- 第二段字符串Payload:
eyJ1aWQiOjEsInNjb3BlIjo4LCJleHAiOjE3MTU3NDAyMjIsImlhdCI6MTYyOTM0MDIyMn0
PAYLOAD是数据载体,可以有自定义数据
{
"uid": "1234567890" // 自定义数据
}
- 第三段字符串Signature:
wuRsF5wvLHbDF_21Pocas8SeXQ315rgBl6wm1LRL2bQ
Signature 部分是对前两部分的签名,防止数据篡改。
JWT的类库
- Java 中的 JWT 有很多类库,关于其优缺点可以在官网查看:https://jwt.io/,这里我们介绍Auth0的JWT的集成使用方式
Auth0 实现的 com.auth0 / java-jwt / 3.3.0
Brian Campbell 实现的 org.bitbucket.b_c / jose4j / 0.6.3
connect2id 实现的 com.nimbusds / nimbus-jose-jwt / 5.7
Les Hazlewood 实现的 io.jsonwebtoken / jjwt / 0.9.0
FusionAuth 实现的 io.fusionauth / fusionauth-jwt / 3.1.0
Vert.x 实现的 io.vertx / vertx-auth-jwt / 3.5.1
具体实现
JWT配置
- pom.xml
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
- application.yml
coisini:
security:
jwt-key: coisini
# 过期时间
token-expired-in: 86400000
JWT工具类
- JwtUtil.java
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @Description JWT工具类
* @author coisini
* @date Aug 18, 2021
* @Version 1.0
*/
@Component
public class JwtUtil {
/**
* key
*/
private static String jwtKey;
/**
* 过期时间
*/
private static Integer expiredTimeIn;
/**
* JWT KEY
* @param jwtKey
*/
@Value("${coisini.security.jwt-key}")
public void setJwtKey(String jwtKey) {
JwtUtil.jwtKey = jwtKey;
}
/**
* 过期时间
* @param expiredTimeIn
*/
@Value("${coisini.security.token-expired-in}")
public void setExpiredTimeIn(Integer expiredTimeIn) {
JwtUtil.expiredTimeIn = expiredTimeIn;
}
/**
* 生成令牌
* @param uid 用户id
* @return
*/
public static String makeToken(Long uid) {
return JwtUtil.getToken(uid);
}
/**
* 获取令牌
* @param uid 用户id
* @param scope 权限分级数字
* @return
*/
private static String getToken(Long uid) {
// 指定算法
Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey);
Map<String, Date> dateMap = JwtUtil.calculateExpiredIssues();
/**
* withClaim() 写入自定义数据
* withExpiresAt() 设置过期时间
* withIssuedAt() 设置当前时间
* sign() 签名算法
*/
return JWT.create()
.withClaim("uid", uid)
.withExpiresAt(dateMap.get("expiredTime"))
.withIssuedAt(dateMap.get("now"))
.sign(algorithm);
}
/**
* 获取自定义数据
* @param token
* @return
*/
public static Optional<Map<String, Claim>> getClaims(String token) {
DecodedJWT decodedJWT;
// 指定算法
Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey);
JWTVerifier jwtVerifier = JWT.require(algorithm).build();
try {
decodedJWT = jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
return Optional.empty();
}
return Optional.of(decodedJWT.getClaims());
}
/**
* 验证Token
* @param token
* @return
*/
public static boolean verifyToken(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(JwtUtil.jwtKey);
JWTVerifier jwtVerifier = JWT.require(algorithm).build();
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
return false;
}
return true;
}
/**
* 计算过期时间
* @return
*/
private static Map<String, Date> calculateExpiredIssues() {
Map<String, Date> map = new HashMap<>();
Calendar calendar = Calendar.getInstance();
Date now = calendar.getTime();
calendar.add(Calendar.SECOND, JwtUtil.expiredTimeIn);
// 当前时间
map.put("now", now);
// 过期时间
map.put("expiredTime", calendar.getTime());
return map;
}
}
测试接口
- JwtController.java
@RestController
@RequestMapping("/jwt")
public class JwtController {
/**
* 获取Token
* @param id
* @return
*/
@GetMapping(value = "/get")
public String getToken(@RequestParam Long id) {
return JwtUtil.makeToken(id);
}
/**
* 验证Token
* @param token
* @return
*/
@PostMapping("/verify")
public Map<String, Boolean> verify(@RequestParam String token) {
Map<String, Boolean> map = new HashMap<>();
Boolean valid = JwtUtil.verifyToken(token);
map.put("is_valid", valid);
return map;
}
}
- 测试结果
- JWT生成的Token应该放在请求头内来传输,后端统一拦截验证,这里留在下篇文章吧。。。
- End -
﹀
﹀
﹀
梦想是咸鱼
关注一下吧

SpringBoot - 集成Auth0 JWT的更多相关文章
- SpringBoot 集成SpringSecurity JWT
目录 1. 简介 1.1 SpringSecurity 1.2 OAuth2 1.3 JWT 2. SpringBoot 集成 SpringSecurity 2.1 导入Spring Security ...
- SpringBoot集成Security,JWT,Swagger全分析
GitHub地址: https://github.com/li-jun0201/springsecuritydemo本项目采用SpringBoot1.5.9, SpringSecurity,JWT, ...
- SpringBoot集成JWT实现token验证
原文:https://www.jianshu.com/p/e88d3f8151db JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github. ...
- SpringBoot集成JWT 实现接口权限认证
JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的, 特别适用于分布式站点 ...
- 【springBoot】springBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- SpringBoot集成security
本文就SpringBoot集成Security的使用步骤做出解释说明.
- springboot集成Actuator
Actuator监控端点,主要用来监控与管理. 原生端点主要分为三大类:应用配置类.度量指标类.操作控制类. 应用配置类:获取应用程序中加载的配置.环境变量.自动化配置报告等与SpringBoot应用 ...
- SpringBoot集成Shiro并用MongoDB做Session存储
之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...
- SpringBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
随机推荐
- LVM磁盘管理实战案例
前言:这是关于centos/linux上的LVM磁盘上的扩容,缩减,磁盘类型等收集做的案例 至于ubuntu系统的磁盘扩容参考:https://www.jianshu.com/p/5dcfcec687 ...
- 深入浅出图神经网络 第6章 GCN的性质 读书笔记
第6章 GCN的性质 第5章最后讲到GCN结束的有些匆忙,作为GNN最经典的模型,其有很多性质需要我们去理解. 6.1 GCN与CNN的区别与联系 CNN卷积卷的是矩阵某个区域内的值,图卷积在空域视角 ...
- ARTS第八周
1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享一篇有观点和思考的技术文章 以下是 ...
- 「CF662C」 Binary Table
「CF662C」 Binary Table 题目链接 题目所给的 \(n\) 很小,于是我们可以考虑这样一种朴素做法:暴力枚举第 \(i\) 行是否翻转,这样每一行的状态就确定了,这时取每一列 \(0 ...
- C语言:数组数据交换
//交换数组中各个变量的值:第1和最后一个交换,第2与倒数第二个交换 #include <stdio.h> int main() { int a[]={1,2,3,4,5,6,7,8,9} ...
- 检测当前手机正在运行的APP
import re #一定要引入,否则不提示错误,但找不到目标def jiance(sjh): aakk="adb -s {0} shell dumpsys activity activit ...
- 学前端的第一门语言HTML
学前端最终要做的就是制作各种各样的网页,html就相当于网页的骨架,所以我们学习前端的第一步就是先学html,接下来学习什么是html. 什么是HTML? HTML指的是超文本标记语言(Hyper T ...
- 【论文阅读】End to End Learning for Self-Driving Cars
前言引用 [1] End to End Learning for Self-Driving Cars从这里开始 [1.1] 这个是相关的博客:2016:DRL前沿之:End to End Learni ...
- HTMLTestRunner.py 文件,已修改完成
""" A TestRunner for use with the Python unit testing framework. It generates a HTML ...
- python开发包之pyecharts
一.python包国内源网址有: 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/ ...