Spring Boot应用中实现基于JWT的登录拦截器,以保证未登录用户无法访问指定的页面

devtools/2025/2/3 11:08:50/

        

目录

一、配置拦截器进行登录校验

1. 在config层设置拦截器

2. 实现LoginInterceptor拦截器

3. 创建JWT工具类

4. 在登录时创建JWT并存入Cookie

二、配置JWT依赖和环境

1. 添加JWT依赖

2. 配置JWT环境

 


本篇博客将为大家介绍了如何在Spring Boot应用中实现基于JWT的登录拦截器,以保证未登录用户无法访问指定的页面。

一、配置拦截器进行登录校验

1. 在config层设置拦截器

我们首先在config层创建一个配置类,用来设置需要拦截的页面。在Spring Boot中,我们可以通过实现WebMvcConfigurer接口来配置拦截器。

创建LoginConfig类:
import com.bim.bimbookshop.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 登录拦截配置类*/
@Configuration   // 表明这个是配置类
public class LoginConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;/*** 配置拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor)  // 添加拦截器.addPathPatterns("/**")  // 配置拦截路径.excludePathPatterns("/login/**", "/static/**", "/templates/**"); // 配置排除路径}
}

这里的addPathPatterns("/**")表示拦截所有路径,而excludePathPatterns用于排除登录、注册等静态资源的路径。例如,/login/**表示排除所有与登录相关的请求。

2. 实现LoginInterceptor拦截器

接下来,我们需要在interceptor层创建一个拦截器类,用来判断用户是否已登录。

创建LoginInterceptor类:
import com.bim.bimbookshop.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 登录拦截器*/
@Component
public class LoginInterceptor implements HandlerInterceptor {/*** 过滤除登录请求外的其他请求* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Cookie[] cookies = request.getCookies();if (cookies != null) {for (Cookie cookie : cookies) {if ("token".equals(cookie.getName())) {String userToken = cookie.getValue();if (!StringUtils.hasText(userToken)) {response.sendError(HttpServletResponse.SC_UNAUTHORIZED); // 未认证}// 解析token并验证try {Claims claims = JwtUtil.parseJWT(userToken);claims.getSubject();  // 如果解析成功,代表用户已登录} catch (Exception e) {System.out.println("Token信息出错");return false; // 如果token无效,返回false,阻止访问}return true;  // 放行}}}return false;  // 如果没有找到token,则返回false,拒绝访问}
}

3. 创建JWT工具类

我们需要一个工具类来生成和解析JWT。这个类会提供生成JWT的功能,并在拦截器中进行解析和验证。

创建JwtUtil类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;/*** JWT工具类*/
public class JwtUtil {// 设置过期时间,单位为毫秒public static final Long JWT_TTL = 60 * 60 * 1000L; // 1小时public static final String JWT_KEY = "qcby";  // 密钥/*** 创建token* @param subject 主题,可以是用户的ID或其他信息* @return JWT token*/public static String createJWT(String subject) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);long expMillis = nowMillis + JWT_TTL;Date expDate = new Date(expMillis);SecretKey secretKey = generalKey();JwtBuilder builder = Jwts.builder().setId(UUID.randomUUID().toString())  // 唯一的ID.setSubject(subject)  // 主题.setIssuer("wd")  // 签发者.setIssuedAt(now)  // 签发时间.signWith(signatureAlgorithm, secretKey)  // 使用HS256算法进行加密.setExpiration(expDate);  // 设置过期时间return builder.compact();}/*** 生成加密后的秘钥* @return SecretKey*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JWT_KEY);return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");}/*** 解析JWT* @param jwt token* @return Claims* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}
}

4. 在登录时创建JWT并存入Cookie

在用户登录成功后,我们会生成一个JWT,并将其保存到浏览器的Cookie中。这样,用户下次访问时,可以通过解析Cookie中的token来验证登录状态。

登录方法:
public ResponseResult Login(Login login, HttpServletResponse response) {// 登录验证逻辑// 登录成功后,根据用户ID生成JWTString token = this.jwtUtil.createJWT(String.valueOf(user.getUserId()));// 将token存入Cookie中Cookie cookie = new Cookie("token", token);cookie.setPath("/");  // 将cookie作用域设置为整个网站cookie.setMaxAge(36000);  // 设置cookie过期时间为10小时response.addCookie(cookie);  // 将cookie添加到响应中return new ResponseResult("登录成功");
}

二、配置JWT依赖和环境

1. 添加JWT依赖

为了能够使用JWT库,我们需要在pom.xml中添加依赖。

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

2. 配置JWT环境

我们可以在application.ymlapplication.properties中配置JWT相关的参数,例如过期时间、密钥等。

spring:...
jwt:secret: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4K67DMlSPXbgG0MPp0gHexpire: 86400000  # 设置过期时间为一天(单位为毫秒)subject: door     # 设置令牌的主题

总结

通过以上步骤,我们在Spring Boot应用中实现了基于JWT的登录认证功能。我们使用拦截器对用户请求进行拦截,只有拥有有效JWT的用户才能访问受保护的资源。这样可以有效地保证系统的安全性和用户体验。


http://www.ppmy.cn/devtools/155702.html

相关文章

线程的状态转换和调度

新建状态New&#xff1a;新创建了一个线程对象 可运行状态Runnable&#xff1a;线程对象创建后&#xff0c;其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中&#xff0c;变得可运行&#xff0c;等待获取CPU的使用权。 运行状态Running&#xff1a;可运行…

python算法和数据结构刷题[6]:二叉树、堆、BFS\DFS

遍历二叉树 前序遍历NLR&#xff1a;先访问根结点&#xff0c;再前序遍历左子树&#xff0c;最后前序遍历右子树。中序遍历LNR&#xff1a;先中序遍历左子树&#xff0c;再访问根结点&#xff0c;最后中序遍历右子树。后序遍历 LRN&#xff1a;先后序遍历左子树&#xff0c;再…

【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…

深度学习查漏补缺:2. 三个指标和注意力机制

一、bachsize, num_epochs, dataset 在训练卷积神经网络&#xff08;CNN&#xff09;或任何其他深度学习模型时&#xff0c;有几个关键参数和概念需要了解&#xff1a;batch size、num epochs 和 dataset。下面是对它们的详细解释&#xff1a; Batch Size&#xff08;批量大小&…

核心集:DeepCore: A Comprehensive Library for CoresetSelection in Deep Learning

目录 一、TL&#xff1b;DR 二、为什么研究核心集&#xff1f; 三、问题定义和如何做 3.1 问题定义 3.2 业界方法 3.2.1 基于几何的方法 3.2.2 基于不确定性的方法 3.2.3 基于误差/损失的方法 3.2.5 GraNd 和 EL2N 分数 3.2.6 重要性采样 3.2.7 基于决策边界的办法 …

小程序-基础加强-自定义组件

前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…

【Linux网络编程】数据链路层

前言&#xff1a; 数据链路层非常简单&#xff0c;对于程序员来说&#xff0c;这里只需要大致了解即可&#xff0c;本篇文章不做重点说明。 数据链路层介绍 数据链路层是OSI位于物理层之上和网络层之下&#xff0c;这一层的报文叫做帧。它的主要任务是确保数据从一个节点可靠地…

基于 YOLOv8+PyQt5 界面自适应的无人机红外目标检测系统项目介绍框架

基于 YOLOv8PyQt5 界面自适应的无人机红外目标检测系统项目介绍框架 【毕业与课程大作业参考】基于yolov8pyqt5界面自适应的无人机红外目标检测系统demo.zip资源-CSDN文库 &#xff08;毕业设计 / 课程大作业参考方案&#xff09; 一、项目背景与意义 无人机在军事侦察、灾害…