Java实现JWT登录认证
文章目录
- 什么是JWT?
- 为什么需要令牌?
- 如何实现?
- 添加依赖:
- JwtUtils.java(生成、解析Token的工具类)
- jwt配置:
- 登录业务逻辑:
- 其他关联代码:
- 测试:
什么是JWT?
JWT(Json Web Token),简单来说就是:web领域中基于json格式的令牌。是最常用的令牌规范。
- 第一部分:Header(头),指定了令牌的签名算法、令牌类型。
- 第二部分:Payload(有效载荷),使用Base64来编码的,不是加密算法,能够解码。因此,该部分不适合存放用户的私密信息(如:密码)。
- 第三部分:Signature(签名),将第一部分和第二部分通过密钥加密得到。

解析Token可以根据第三部分解密得到前两部分的信息,再比对前端传来的用户信息,完成校验。
Token验证失败的情况?
- token过期
- 密钥不正确
- 篡改了头部、载荷等
为什么需要令牌?
- 承载了一定的数据信息,减少数据库访问次数
- 具有一定的防伪功能
如何实现?
该部分代码不需要硬记,理解后直接使用即可。
添加依赖:
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
JwtUtils.java(生成、解析Token的工具类)
public class JwtUtil {/*** 生成Token* @param secretKey* @param ttlMillis* @param claims* @return*/public static String createToken(String secretKey, long ttlMillis, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成token的过期时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** 解析token* @param secretKey* @param token* @return*/public static Claims parseToken(String secretKey, String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}}
jwt配置:
-
application.yaml:
user:jwt:# 设置jwt签名加密时使用的秘钥user-secret-key: xxx# 设置jwt过期时间user-ttl: 7200000# 设置前端传递过来的令牌名称user-token-name: token -
JwtProperties:
@Component @ConfigurationProperties(prefix = "user.jwt") @Data public class JwtProperties {private String userSecretKey;private long userTtl;private String userTokenName; } -
JwtClaimsConstant(管理常量):
public class JwtClaimsConstant {public static final String USER_ID = "userId"; } -
jwt拦截器:
@Component @Slf4j public class JwtInterceptor implements HandlerInterceptor {@Resourceprivate JwtProperties jwtProperties;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1. 获取用户信息String token = request.getHeader(jwtProperties.getUserTokenName());//2. 判断用户信息是否有效,存入ThreadLocaltry {Claims claims = JwtUtil.parseToken(jwtProperties.getUserSecretKey(), token);String userInfo = claims.get(JwtClaimsConstant.USER_ID).toString();if (StrUtil.isNotBlank(userInfo)){UserContext.setUser(Long.valueOf(userInfo));}//3. 放行return true;}catch (Exception e){//4. 不通过response.setStatus(401);return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//清除用户信息UserContext.removeUser();} } -
WebMvc配置(添加jwt拦截器)
@Configuration public class WebConfig implements WebMvcConfigurer {@Resourceprivate JwtInterceptor jwtInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(jwtInterceptor).addPathPatterns("/user/**").excludePathPatterns("/user/user/login");} } -
UserContext(存储用户登录信息,方便其他业务需求获取)
public class UserContext {private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();/*** 获取用户信息* @return*/public static Long getUser() {return threadLocal.get();}/*** 设置用户信息* @param userId*/public static void setUser(Long userId){threadLocal.set(userId);}/*** 移除用户信息*/public static void removeUser(){threadLocal.remove();} }
登录业务逻辑:
-
controller层:
@RestController @RequestMapping("/user/user") @Slf4j public class UserController {@Resourceprivate UserService userService;@PostMapping("/login")public UserLoginVO login(@RequestBody UserLoginDTO userLoginDTO){log.info("用户登录:{}",userLoginDTO);return userService.login(userLoginDTO);} } -
service层:
public interface UserService {UserLoginVO login(UserLoginDTO userLoginDTO); }@Service @Slf4j public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Resourceprivate JwtProperties jwtProperties;@Overridepublic UserLoginVO login(UserLoginDTO userLoginDTO) {String username = userLoginDTO.getUsername();String password = userLoginDTO.getPassword();//1. 校验用户名和密码UserLogin userLogin = userMapper.getUserByName(username);if (userLogin == null){throw new BaseException("用户名或密码错误");}password = DigestUtils.md5DigestAsHex(password.getBytes());if (!password.equals(userLogin.getPassword())){throw new BaseException("用户名或密码错误");}//2. 生成tokenHashMap<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.USER_ID, userLogin.getId());String token = JwtUtil.createToken(jwtProperties.getUserSecretKey(),jwtProperties.getUserTtl(),claims);//3. 封装voUserLoginVO loginVO = UserLoginVO.builder().token(token).userId(userLogin.getId()).username(userLogin.getUsername()).build();return loginVO;} } -
mapper层:
@Mapper public interface UserMapper {UserLogin getUserByName(String username); }<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.sky.user.mapper.UserMapper"><select id="getUserByName" resultType="com.sky.user.pojo.entity.UserLogin">select *from user_login where username = #{username} and is_delete = 0;</select> </mapper>
其他关联代码:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserLoginDTO {/*** 用户名*/private String username;/*** 密码*/private String password;}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserLoginVO {private String token;private Long userId;private String username;
}
测试:
登录接口:

其他接口:


以上为个人学习分享,如有问题,欢迎指出:)
相关文章:
Java实现JWT登录认证
文章目录 什么是JWT?为什么需要令牌?如何实现?添加依赖:JwtUtils.java(生成、解析Token的工具类)jwt配置:登录业务逻辑:其他关联代码:测试: 什么是JWT? JWT(Json Web Token&…...
「Mac畅玩鸿蒙与硬件20」鸿蒙UI组件篇10 - Canvas 组件自定义绘图
Canvas 组件在鸿蒙应用中用于绘制自定义图形,提供丰富的绘制功能和灵活的定制能力。通过 Canvas,可以创建矩形、圆形、路径、文本等基础图形,为鸿蒙应用增添个性化的视觉效果。本篇将介绍 Canvas 组件的基础操作,涵盖绘制矩形、圆…...
山东路远生态科技有限公司竣工投产仪式暨产品发布会圆满举行
第二十届三中全会于2024年7月15日至18日在北京举行。全会审议通过了《关于进一步全面深化改革、推进中国式现代化的决定》。其中提到,“要健全因地制宜发展新质生产力体制机制”。 新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级而催生的当代先进生产力…...
java: 题目:银行账户管理系统
题目:银行账户管理系统 设计一个简单的银行账户管理系统。要求实现以下功能: 1. 创建一个银行账户 BankAccount 类,该类具有以下属性:accountNumber(账户号码,类型为 String) balanceÿ…...
PH热榜 | 2024-11-06
DevNow 是一个精简的开源技术博客项目模版,支持 Vercel 一键部署,支持评论、搜索等功能,欢迎大家体验。 Github:https://github.com/LaughingZhu/DevNow 1. MindOne Builder 标语:这是一个“设计优先”的应用构建工具…...
五、Java并发 Java Google Guava 实现
Guava 是托管在 Github.com 上的流行的 Google 开源的 Java 线程池库。 Guava 包含了许多有用的并发类,同时还包含了几个方便的 ExecutorService 实现,但这些实现类都无法通过直接实例化或子类化来创建实例。取而代之的是提供了 MoreExecutors 助手类来…...
ssm公交车信息管理系统+vue
系统包含:源码论文 所用技术:SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习,获取源码看文章最下面 需要定制看文章最下面 目 录 摘要 I Abstract II 第1章 绪 论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 国内外研究现状 …...
如何删除react项目的默认图标,使在浏览器中不显示默认图标favicon.ico
要删除 React 项目的默认图标,使在浏览器中不显示默认图标favicon.ico,其实有两种方法: 方法一 方法要点:删除掉 public 目录下的 favicon.ico 文件,再用浏览器访问时,如果加载不到图标文件,就…...
【React】react-app-env.d.ts 文件
在使用 create-react-app 生成的 TypeScript 项目模板中,react-app-env.d.ts 文件的作用是为 React 应用中的全局变量和类型进行声明。 全局类型声明:react-app-env.d.ts 文件会引入 react-scripts 提供的全局类型定义,这些类型定义扩展了 Ty…...
设计模式讲解01-建造者模式(Builder)
1. 概述 建造者模式也称为:生成器模式 定义:建造者模式是一种创建型设计模式,它允许你将创建复杂对象的步骤与表示方式相分离。 解释:建造者模式就是将复杂对象的创建过程拆分成多个简单对象的创建过程,并将这些简单…...
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 wflow-web是一个开源的工作流设计器,它支持可视化拖拽表单组件,动态任意层级结构审批节点,以及复杂流程条件的设置…...
Promise 简单介绍及深入挖掘
一、什么是 Promise? 在 JavaScript 中,Promise 是用于处理异步操作的一种方式。它代表了一个 可能 在将来某个时间点完成或失败的操作的结果。Promise 使得我们能够优雅地处理异步代码,避免了回调地狱(Callback Hell)…...
103 - Lecture 1
Introduction to Database 一、Introduction to Database Systems 1. 数据的定义 What is Data? EX: data could be a docx file storing your project status report; data could be a spreadsheet containing information • 数据只有在设计的场景中才有意义。ÿ…...
Ubuntu 20.04禁用或者移除 cloud-init
1、禁用cloud-init 这是最简单最安全的方法,在 /etc/cloud 目录下创建 cloud-init.disabled 文件重启后生效。删除该文件就可以恢复 # 创建cloud-init.disabled文件 sudo touch /etc/cloud/cloud-init.disabled # 重启 reboot 2、移除 cloud-init 软件包及文件夹…...
DevOps开发运维简述
DevOps平台是一套集成的解决方案,旨在协调软件开发(Development)和信息技术运维(Operations)。它促进跨功能团队合作,实现自动化流程,确保持续集成与持续交付(CI/CD)。 一…...
C++之list的使用
在C中,std::list 是一个双向链表,它允许在列表的任何位置高效地插入和删除元素。以下是一些基本的使用方式: 包含头文件 要使用 std::list,首先需要包含头文件 <iostream> 和 /list>。 #include <iostream> #in…...
nginx配置代理地址
1,配置19上的代理 location /jmis/ { alias D:/images/; autoindex on; sendfile on; } 2.在18服务器上访问19的图片。18服务器nginx代理 proxy_set_header 指令用于在发送给后端服务器的请求中添加或修改指定的HTTP头信息。 proxy_p…...
国际版JAVA同城打车源码同城服务线下结账系统源码适配PAD支持Android+IOS+H5
一、数据中心 总用户数今日接单数量今日新增今日收入本月新增本月收入本年新增本年收入 二、用户中心 全部用户普通用户师傅用户推广员用户 三、财务中心 提现管理收入统计提现统计充值统计充值记录保证金管理平台收入统计 四、首页装修 轮播图分享图语音播报配置 五…...
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
2024-10-31,由清华大学和北京大学共同创建的AndroidLab数据集,为安卓自主代理的训练和评估提供了一个包含操作环境、行动空间和可复现基准的系统框架,这对于推动安卓代理技术的发展具有重要意义。 数据集地址:Android Instruct|A…...
Java--正则表达式入门指南
正则表达式(Regular Expression)是一种用于匹配字符串中字符模式的工具。在Java中,正则表达式的使用主要依赖于java.util.regex包,其中最重要的两个类是Pattern和Matcher。今天将探讨正则表达式的基础概念、书写规则、常用方法&am…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
