springboot+vue前后端分离项目加入jwt

目前只写了后端方面的,马上在补充一下前端的吧

1. 后端处理过程

依赖

复制代码
<!-- JJWT 核心 API -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <!-- JJWT 实现类(运行时依赖) -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <!-- JSON 序列化(Jackson) -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>

添加jwt配置文件

复制代码
# JWT 核心配置(必须添加)
jwt:
  # 密钥(必须是32位以上字符串,可随便写,生产环境要随机生成)
  secret: abcdefghijklmnopqrstuvwxyz1234567890abcdef
  # 过期时间(秒):10小时 = 36000秒
  expire-time: 36000
复制代码
mybatis-plus:
  global-config:
    banner: false  # 关闭 MyBatis-Plus 启动 Logo

目录结构

jwtutil.java

复制代码
package com.example.wms001.common;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

@Component
public class JwtUtil {
    // 从配置文件读取密钥(application.yml 配置不变)
    @Value("${jwt.secret}")
    private String secret;

    // Token过期时间(秒)
    @Value("${jwt.expire-time}")
    private Long expireTime;

    // 生成密钥
    private SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(secret.getBytes());
    }

    // 生成Token(逻辑不变)
    public String generateToken(String userId, Map<String, Object> claims) {
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + expireTime * 1000);

        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userId)
                .setIssuedAt(now)
                .setExpiration(expireDate)
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    // 解析Token(逻辑不变)
    public Claims parseToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            throw new RuntimeException("Token已过期");
        } catch (JwtException e) {
            throw new RuntimeException("Token无效");
        }
    }

    // 获取用户ID(逻辑不变)
    public String getUserIdFromToken(String token) {
        return parseToken(token).getSubject();
    }

    // 验证Token(逻辑不变)
    public boolean validateToken(String token) {
        try {
            parseToken(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

jwt拦截器Jwtinterceptr.java

复制代码
package com.example.wms001.common;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest; // 关键:jakarta而非javax
import jakarta.servlet.http.HttpServletResponse;

@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtUtil jwtUtil; // 注入common包的JwtUtil

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 排除登录接口
        String requestURI = request.getRequestURI();
        if (requestURI.contains("/user/login")) {
            return true;
        }

        // 获取Token
        String token = request.getHeader("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            throw new RuntimeException("请先登录");
        }
        token = token.replace("Bearer ", "");

        // 验证Token
        if (!jwtUtil.validateToken(token)) {
            throw new RuntimeException("Token无效或已过期");
        }

        // 存入用户ID到请求域
        String userId = jwtUtil.getUserIdFromToken(token);
        request.setAttribute("userId", userId);

        return true;
    }
}

配置文件

复制代码
package com.example.wms001.common;

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 WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private JwtInterceptor jwtInterceptor; // 注入common包的拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");
    }
}
相关推荐
Java编程爱好者15 小时前
这 4 种 SQL 写法,数据量一大就是生产事故(SQL 性能篇)
后端
小旭952715 小时前
分布式事务 Seata 详解 + 链路追踪 SkyWalking 实战
java·分布式·后端·信息可视化·skywalking
曹牧15 小时前
Spring:@RequestMapping 注解匹配顺序
java·后端·spring
账号已注销free15 小时前
Vue3 defineProps使用指南
vue.js
LIO15 小时前
Pinia 极简指南:Vue 3 官方状态管理库
前端·vue.js
AI攻城狮15 小时前
DeepSeek 的 Vision 能力要来了吗?
人工智能·后端·openai
用户6224757584616 小时前
面试官问我:"如何实现你项目中的这块代码."我说:"看好了."
后端
空中海16 小时前
Nacos 2: Spring Boot Demo 实战
java·spring boot·后端
阿丰资源16 小时前
基于Spring Boot的美容院管理系统(附源码+数据库+文档)
数据库·spring boot·后端
TE-茶叶蛋16 小时前
Spring自动配置分析
java·后端·spring