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

目录

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

[1. 在config层设置拦截器](#1. 在config层设置拦截器)

[2. 实现LoginInterceptor拦截器](#2. 实现LoginInterceptor拦截器)

[3. 创建JWT工具类](#3. 创建JWT工具类)

[4. 在登录时创建JWT并存入Cookie](#4. 在登录时创建JWT并存入Cookie)

二、配置JWT依赖和环境

[1. 添加JWT依赖](#1. 添加JWT依赖)

[2. 配置JWT环境](#2. 配置JWT环境)


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

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

1. 在config层设置拦截器

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

创建LoginConfig类:
java 复制代码
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 {

    @Autowired
    private LoginInterceptor loginInterceptor;

    /**
     * 配置拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)  // 添加拦截器
                 .addPathPatterns("/**")  // 配置拦截路径
                 .excludePathPatterns("/login/**", "/static/**", "/templates/**"); // 配置排除路径
    }
}

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

2. 实现LoginInterceptor拦截器

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

创建LoginInterceptor类:
java 复制代码
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
     */
    @Override
    public 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类:
java 复制代码
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来验证登录状态。

登录方法:
java 复制代码
public ResponseResult Login(Login login, HttpServletResponse response) {
    // 登录验证逻辑

    // 登录成功后,根据用户ID生成JWT
    String 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中添加依赖。

java 复制代码
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

2. 配置JWT环境

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

java 复制代码
spring:
    ...
jwt:
  secret: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4K67DMlSPXbgG0MPp0gH
  expire: 86400000  # 设置过期时间为一天(单位为毫秒)
  subject: door     # 设置令牌的主题

总结

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

相关推荐
IT_陈寒24 分钟前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
CaffeinePro1 小时前
Pydantic深度使用:数据校验、枚举、ORM映射
后端·fastapi
Chenyiax2 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH2 小时前
Koa和Express的区别
后端
MariaH2 小时前
Koa框架的使用
后端
luckdewei3 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某4 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy4 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom4 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
用户1474853079749 小时前
CodeX使用Skill生成游戏美术和音乐资源,一分钟入门
后端