杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版)
杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版)
在现代Web应用和API开发中,JSON Web Token (JWT) 是一种广泛使用的认证和鉴权机制。JWT不仅简化了认证流程,还提供了安全的令牌传递方式,使得跨域认证变得更加容易。本文将详细介绍如何使用JWT进行API认证和鉴权,并提供一个简单的示例。
什么是JSON Web Token (JWT)?
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在网络应用之间安全地传输信息。JWT是一个紧凑的、URL安全的字符串,可以包含声明(claims),这些声明用于传输关于实体(通常是用户)的信息。JWT通常由三部分组成:
- Header:包含令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
- Payload:包含声明,即关于实体的信息。声明可以分为注册声明、公有声明和私有声明。
- Signature:用于验证消息的完整性和确保消息来自可信方。
一个典型的JWT可能如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT的工作原理
- 生成JWT:
● 用户通过用户名和密码进行登录。
● 服务器验证用户身份后,生成一个JWT。
● 服务器将JWT返回给客户端。 - 使用JWT:
● 客户端在每次请求中将JWT放在请求头的Authorization字段中,格式为Bearer 。
● 服务器接收到请求后,解析JWT并验证其签名。
● 服务器根据JWT中的信息进行鉴权,决定是否允许请求。
使用JWT进行API认证和鉴权
第一步:我们首先使用maven引入相关包
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
第二步:我们编写类AuthService,目的是生成对应的token信息
/*** @author Sam Zhang* @date 2024-11-09 08:54:54* @since 0.0.1* 注释:登录用户生成token信息*/
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;public class AuthService {private static final String SECRET_KEY = "analysis_service";private static final long EXPIRATION_TIME = 86400000; // 1 day in milliseconds:86400000/**** @author Sam Zhang* @date 2024/11/9 9:00* @Description: 验证用户名密码,并且进行token生成* @param: username:目前写死用户名密码* @param: password:目前写死用户名密码* @return * @return java.lang.String*/public String login(String username, String password) {// 这里验证用户名和密码// 验证成功后生成Tokenif(username.equals("authUser") && password.equals("authPasswd")){return generateToken(username);}else{return "username or password is incorrect";}}/*** @author Sam Zhang* @date 2024/11/9 9:04* @Description: 生成token* @param: username:通过用户名生成token* @return * @return java.lang.String*/private String generateToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}
}
第三步:我们编写类TokenService,对生成的token进行后续校验使用
/*** @author Sam Zhang* @date 2024-11-09 09:03:49* @since 0.0.1* 注释:验证Token的合法性*/
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;public class TokenService {private static final String SECRET_KEY = "analysis_service";/**** @author Sam Zhang* @date 2024/11/9 9:16* @Description: 检查token是否还有效* @param: token:获取的token值* @return * @return boolean*/public boolean isTokenValid(String token) {if (token != null && token.startsWith("Bearer:[\"")) {token = token.substring(9,token.length()-2);try {// 解析Token并验证Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);return true; // 验证通过} catch (Exception e) {return false; // 验证失败}}else {return false; // 验证失败}}public String getUsernameFromToken(String token) {Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();return claims.getSubject();}
}
第四步:对外暴露接口,我们使用SpringBoot框架进行实现,在controller层新建类AuthService,我们提供如下对外接口
import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;/*** @author Sam Zhang* @date 2024-11-09 09:18:33* @since 0.0.1* 注释:鉴权相关服务*/@RestController
public class AuthService {@AutowiredGenerateAuthlmpl generateAuthlmpl;@ApiOperation(value = "使用用户名密码进行鉴权以获得token信息", notes = "使用用户名密码进行鉴权以获得token信息")@ApiImplicitParams({@ApiImplicitParam(name = "jsonObject", value = "后续接口调用都需要鉴权",required=true,paramType = "body")})@PostMapping(value = "/gettoken",produces = "application/json;charset=UTF-8")public JSONObject getToken(@RequestBody JSONObject jsonObject) {JSONObject result = new JSONObject();CheckRequestBody checkRequestBody = new CheckRequestBody();boolean b = checkRequestBody.checkGetToken(jsonObject);if(!b){result.append("result",GETTOKENMISSBODY);result.append("msg","请检查请求body是否缺少对应字段");return result;}//检查没有问题以后,获取对应的字段信息String username = jsonObject.getStr("username");String password = jsonObject.getStr("password");//数据处理后传给后端进行token生成LoginInfos loginInfos = new LoginInfos();loginInfos.setUsername(username);loginInfos.setPassword(password);result = generateAuthlmpl.generateAuth(loginInfos);//返回结果return result;}}
第五步:当我们需要获取对应token以后,我们需要对后续的接口进行接口验证,我们其他接口的示例如下
import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author Sam Zhang(27988)* @date 2024-11-06 10:51:40* @since 0.0.1* 注释:文件处理相关接口*/@RestController
public class DealWithFiles {private final Logger log = LoggerFactory.getLogger(this.getClass());ExecutorService executorService = Executors.newFixedThreadPool(1);@AutowiredDownLoadLogslmpl downLoadLogslmpl;@ApiOperation(value = "下载日志并且进行分析", notes = "下载日志并且进行分析")@ApiImplicitParams({@ApiImplicitParam(name = "Authorization", value = "获取的token信息",required=true,paramType = "header"),@ApiImplicitParam(name = "jsonObject", value = "分析接口请求内容",required=true,paramType = "body")})@PostMapping(value = "/analysis",produces = "application/json;charset=UTF-8")public JSONObject analysisLogs(@RequestHeader("Authorization") String authHeader, @RequestBody JSONObject jsonObject) {JSONObject result = new JSONObject();//校验消息头TokenService tokenService = new TokenService();boolean tokenValid = tokenService.isTokenValid(authHeader);if(!tokenValid){result.append("result",UNAUTH);result.append("msg","鉴权校验失败,请检查");return result;}//后续代码省略}
}
接口验证
鉴权接口
- 接口名称:/gettoken
- 接口方法:post
- 消息头:Content-Type:application/json;charset=UTF-8
- 编码:UTF-8
- 请求消息体格式:Json格式
{"username": "XXX","password": "XXX"
}
● username:鉴权用户名,当前只有这么1个。
● password:鉴权密码,当前只有这么1个。
6. 响应消息体格式:Json格式
{"msg": ["token生成成功"],"token": ["eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoVXNlciIsImlhdCI6MTczMTMwMzMzMywiZXhwIjoxNzMxMzg5NzMzfQ.DlxEJjQpITT_y_5W_lZS67hVJ1PTHQdMI7De1mQKH04"],"result": [100],"username": ["XXX"]
}
● msg:返回的消息格式。
● token:返回的token信息。
● result:返回的结果码,100表示请求成功。
● username:对应用户鉴权。
需要被验证接口
- 接口名称:/analysis
- 接口方法:post
- 消息头:
● Content-Type:application/json;charset=UTF-8
● Authorization: Bearer:[“token信息”],样例:Authorization: Bearer:[“eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoVXNlciIsImlhdCI6MTczMTMwMzMzMywiZXhwIjoxNzMxMzg5NzMzfQ.DlxEJjQpITT_y_5W_lZS67hVJ1PTHQdMI7De1mQKH04”]
● 消息头如果验证不通过,则会有如下结果返回
{"msg":["鉴权校验失败,请检查"],"result":[104]
}
至此,我们基于JSON Web Token (JWT)的鉴权完成。
相关文章:
杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版)
杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版) 在现代Web应用和API开发中,JSON Web Token (JWT) 是一种广泛使用的认证和鉴权机制。JWT不仅简化了认证流程,还提供了安全的令牌传递方式,使得跨域认证…...
建设展示型网站企业渠道用户递达
展示型网站的主要作用便是作为企业线上门户平台、信息承载形式、拓客咨询窗口、服务/产品宣传订购、其它内容/个人形式呈现等,网站发展多年,现在依然是企业线上发展的主要工具之一且有建设的必要性。 谈及整体价格,自制、定制开发、SAAS系统…...
如何通过AB测试找到最适合的Yandex广告内容
想要在Yandex上找到最能吸引目标受众的广告内容,A/B测试是一个不可或缺的步骤。通过对比不同版本的广告,我们可以发现哪些元素最能引起用户的共鸣。首先,设计两个或多个广告版本,确保每个版本在标题、文案、图片等关键元素上有所不…...
AI写作(四)预训练语言模型:开启 AI 写作新时代(4/10)
一、预训练语言模型概述 预训练语言模型在自然语言处理领域占据着至关重要的地位。它以其卓越的语言理解和生成能力,成为众多自然语言处理任务的关键工具。 预训练语言模型的发展历程丰富而曲折。从早期的神经网络语言模型开始,逐渐发展到如今的大规…...
解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url
解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url 第一类情况 在anaconda创建新环境时,使用如下代码 conda create -n charts python3.7 错误原因: 默认镜像源访问速度过慢,会导致超时从而导致更新和下载失败。 解决方…...
员工绩效统计出现很多小数点,处理方法大全
1.直接通过数据库修改数据类型 譬如采用DECIMAL类型 2.float 降低小数点位数 3.php 采用round函数...
【启明智显分享】5G CPE为什么适合应用在连锁店中?
连锁门店需要5G CPE来满足其日益增长的网络需求,提升整体运营效率和竞争力。那么为什么5G CPE适合连锁店应用呢,小编为此做了整理,主要是基于以下几个方面的原因: 一、高效稳定的网络连接 1、高速数据传输: 5G CPE能…...
十大经典排序算法-希尔排序与归并排序
1、希尔排序 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序是基于插入排序的以下两点性质而提出改进方法的: 插入排序在对几乎已经排好序的数据操作时,效率高&…...
gitlab和jenkins连接
一:jenkins 配置 安装gitlab插件 生成密钥 id_rsa 要上传到jenkins,id_rsa.pub要上传到gitlab cat /root/.ssh/id_rsa 复制查看的内容 可以看到已经成功创建出来了对于gitlab的认证凭据 二:配置gitlab cat /root/.ssh/id_rsa.pub 复制查…...
Qt Event事件系统小探2
目录 事件过滤器 来看一个例子 拖放事件和拖放操作 Qt官方文档给出的说明 拖放 拖放类 配置 拖动 放置 覆盖建议的操作 子类化复杂窗口小部件 拖放操作 添加新的拖放类型 放置操作 放置矩形 剪贴板 其他函数的介绍 事件过滤器 我们知道,有的时候想…...
[2024最新] java八股文实用版(附带原理)---java集合篇
介绍一下常见的list实现类? ArrayList 线程不安全,内部是通过数组实现的,继承了AbstractList,实现了List,适合随机查找和遍历,不适合插入和删除。排列有序,可重复,当容量不够的时候…...
pytorch tensor在CPU和GPU之间转换,numpy之间的转换
# input input.cpu().numpy() input input.cpu().detach().numpy() # 有gradCPU tensor转GPU tensor: cpu_imgs.cuda()GPU tensor 转CPU tensor: gpu_imgs.cpu()numpy转为CPU tensor: torch.from_numpy( imgs )4.CPU tensor转为numpy数…...
【电压分层控制】光储三相并网下垂控制,直流微电网协调母线电压分层控制
摘要 本文研究了一种基于电压分层控制的光伏与储能系统并网控制策略。通过下垂控制和分层控制方法实现直流微电网的协调运行,提高系统动态响应和稳态性能。仿真结果表明,该控制策略能够在不同工况下有效稳定母线电压,并实现负载功率合理分配…...
【CSS】absolute定位的默认位置
position: absolute; 属性会使元素脱离正常的文档流,并相对于最近的非 static 定位祖先元素进行定位。如果没有这样的祖先元素,则相对于初始包含块(通常是视口)进行定位。 但是当top和left没有指定具体值时,元素的在上…...
遗传算法与深度学习实战——利用进化计算优化深度学习模型
遗传算法与深度学习实战——利用进化计算优化深度学习模型 0. 前言1. 利用进化计算优化深度学习模型2. 利用进化策略优化深度学习模型3. 利用差分计算优化深度学习模型相关链接 0. 前言 我们已经学习了使用进化策略 (Evolutionary Strategies, ES) 和差分进化 (Differential E…...
计算机视觉 ---图像读取与显示(OpenCV与Matplotlib)
前言 本文分别介绍了使用 OpenCV 和 Matplotlib 进行图像读取与显示的方法,如 cv2.imread ()、cv2.imshow ()、plt.imread ()、plt.imshow () 等,并提及了使用 OpenCV 时的注意事项。 OpenCV与Matplotlib图像读取与显示的差异 图像读取: Op…...
XML Schema 字符串数据类型
XML Schema 字符串数据类型 1. 概述 XML Schema 是一种用于定义 XML 文档结构和内容的语言。它提供了一种强大的机制来描述 XML 数据的类型、结构和约束。在 XML Schema 中,字符串数据类型是一种基本数据类型,用于表示文本数据。 2. 字符串数据类型 …...
Spring Boot 读取 yml 并映射至实体
application-base.yml app:# 附件存储路径upload-attachments: /data/attachments/# 报告导出详情 url - 前端score-detail-url: ${app.host.web}/#/process/start?processNo{}# api 文件下载 urlfile-download-url: ${app.host.web}/prod-api/sys_file_info/download/{}?fu…...
/// ts中的三斜线指令 | 前端
第一次看到注意到这行代码,不知道的还以为是注释呢,查了资料才知道这是typescript中的三斜线指令,那有什么作用呢? 1. 这行代码是TypeScript中的一个三斜线指令(Triple-Slash Directive),用于…...
什么岗位需要学习 OpenGL ES ?说说 3.X 的新特性
什么是 OpenGL ES OpenGL ES 是一种为嵌入式系统和移动设备设计的3D图形API(应用程序编程接口)。它是标准 OpenGL 3D 图形库的一个子集,专门为资源受限的环境(如手机、平板电脑、游戏机和其他便携式设备)进行了优化。 由于其在移动设备上的广泛适用性,OpenGL ES是学习移…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...
2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】
1、获取景点详情的请求【my_api.js】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http(/login/getWXSessionKey, {code,avatar}); };//…...
