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");
    }
}
相关推荐
Elaine33610 分钟前
基于Django框架的静态个人名片网站设计
后端·python·django·mvt
道友可好11 分钟前
3 个人,100 万行代码,一行都没人写:OpenAI 的 Harness Engineering 实验
前端·人工智能·后端
W_LuYi18521 分钟前
Tauri + Rust + Vue 3 打造极速轻量桌面应用
java·开发语言·vue.js·rust
qq43569470135 分钟前
Vue03
javascript·vue.js
Yeats_Liao44 分钟前
8:Servlet生命周期-Java Web
后端
用户549591657501 小时前
TinyVue Tree树形控件完全指南
vue.js
Soofjan1 小时前
其它(5):Bleve 全文检索
后端
Gopher_HBo1 小时前
Go语言学习笔记(七)并发
后端
Momo__1 小时前
SSR 懒水合四件套 — 99%的人不知道 Vue 3.5 藏了这些水合策略
前端·vue.js·性能优化
智碳未来科技有限公司1 小时前
工业双碳实践:基于 SpringBoot + 若依的智碳能源管理系统(zhitan-ems)源码深度解析与落地实战
spring boot·后端·能源