Spring Boot 1.x(基于Spring 4)中使用Java 8实现Token

  1. 添加依赖(pom.xml)

xml

复制代码
<!-- Spring Boot 1.x 基础依赖 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.22.RELEASE</version> <!-- 兼容Java 8的版本 -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- JWT支持 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
    
    <!-- 如果需要数据库 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

2. JWT工具类

java

复制代码
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtTokenUtil {
    
    private static final String SECRET_KEY = "your-secret-key-change-in-production";
    private static final long EXPIRATION_TIME = 86400000L; // 24小时
    
    /**
     * 生成Token
     */
    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("sub", username);
        claims.put("created", new Date());
        
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }
    
    /**
     * 验证Token
     */
    public Boolean validateToken(String token, String username) {
        final String usernameFromToken = getUsernameFromToken(token);
        return (usernameFromToken.equals(username) && !isTokenExpired(token));
    }
    
    /**
     * 从Token获取用户名
     */
    public String getUsernameFromToken(String token) {
        return getClaimsFromToken(token).getSubject();
    }
    
    /**
     * 获取Token过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        return getClaimsFromToken(token).getExpiration();
    }
    
    /**
     * 解析Token
     */
    private Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
    
    /**
     * 判断Token是否过期
     */
    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }
}

3. Token拦截器

java

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TokenInterceptor implements HandlerInterceptor {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        
        // 放行OPTIONS请求
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        
        // 获取Token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
        }
        
        // Token验证
        if (token == null || !validateToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"无效的Token或Token已过期\"}");
            return false;
        }
        
        // 将用户名存入请求
        String username = jwtTokenUtil.getUsernameFromToken(token);
        request.setAttribute("username", username);
        return true;
    }
    
    private boolean validateToken(String token) {
        try {
            String username = jwtTokenUtil.getUsernameFromToken(token);
            return jwtTokenUtil.validateToken(token, username);
        } catch (Exception e) {
            return false;
        }
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                          Object handler, ModelAndView modelAndView) throws Exception {
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                               Object handler, Exception ex) throws Exception {
    }
}

4. Web配置类

java

复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 排除登录和注册接口
        registry.addInterceptor(new TokenInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/auth/login")
                .excludePathPatterns("/api/auth/register");
    }
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(false)
                .maxAge(3600);
    }
}

5. 认证控制器

java

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    /**
     * 登录接口
     */
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        // 1. 验证用户名密码(这里简化处理,实际应从数据库验证)
        if (!"admin".equals(loginRequest.getUsername()) || 
            !"123456".equals(loginRequest.getPassword())) {
            Map<String, Object> error = new HashMap<>();
            error.put("code", 401);
            error.put("message", "用户名或密码错误");
            return ResponseEntity.status(401).body(error);
        }
        
        // 2. 生成Token
        String token = jwtTokenUtil.generateToken(loginRequest.getUsername());
        
        // 3. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "登录成功");
        result.put("data", token);
        result.put("username", loginRequest.getUsername());
        
        return ResponseEntity.ok(result);
    }
    
    /**
     * 注册接口
     */
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest) {
        // 注册逻辑...
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "注册成功");
        return ResponseEntity.ok(result);
    }
    
    /**
     * 获取用户信息(需要Token验证)
     */
    @GetMapping("/userInfo")
    public ResponseEntity<?> getUserInfo(@RequestAttribute String username) {
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("username", username);
        result.put("roles", new String[]{"USER"});
        return ResponseEntity.ok(result);
    }
}

// 请求参数类
class LoginRequest {
    private String username;
    private String password;
    
    // getters and setters
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}

class RegisterRequest {
    private String username;
    private String password;
    private String email;
    
    // getters and setters
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

6. 响应封装类(可选)

java

复制代码
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    
    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
    
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "成功", data);
    }
    
    public static ApiResponse<?> error(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }
    
    // getters and setters
    public int getCode() { return code; }
    public void setCode(int code) { this.code = code; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public T getData() { return data; }
    public void setData(T data) { this.data = data; }
}

7. 前端使用示例

javascript

复制代码
// 登录获取Token
async function login(username, password) {
    const response = await fetch('/api/auth/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ username, password })
    });
    
    const result = await response.json();
    if (result.code === 200) {
        // 存储Token到localStorage
        localStorage.setItem('token', result.data);
        localStorage.setItem('username', result.username);
    }
    return result;
}

// 带Token的请求
async function getUserInfo() {
    const token = localStorage.getItem('token');
    
    const response = await fetch('/api/auth/userInfo', {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        }
    });
    
    return await response.json();
}

// 请求拦截器示例(axios)
axios.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});

axios.interceptors.response.use(response => {
    return response;
}, error => {
    if (error.response.status === 401) {
        // Token过期或无效,跳转到登录页
        window.location.href = '/login';
    }
    return Promise.reject(error);
});

8. 配置文件(application.yml)

yaml

复制代码
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/yourdb
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

注意事项

  1. 安全性:生产环境需要将SECRET_KEY存储在安全的配置中,不要硬编码

  2. Token过期:根据需求调整Token过期时间

  3. 刷新Token:可以添加刷新Token机制

  4. HTTPS:生产环境必须使用HTTPS

  5. Token存储:前端应使用HttpOnly的cookie或localStorage存储Token

相关推荐
汤姆yu2 小时前
2026基于springboot的在线招聘系统
java·spring boot·后端
计算机学姐2 小时前
基于SpringBoot的校园社团管理系统
java·vue.js·spring boot·后端·spring·信息可视化·推荐算法
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-企业级教育考试系统核心架构(完善版)
开发语言·人工智能·spring boot·python·架构·领域驱动
java1234_小锋2 小时前
Java高频面试题:SpringBoot如何自定义Starter?
java·spring boot·面试
落霞的思绪2 小时前
Spring AI Alibaba 集成 Redis 向量数据库实现 RAG 与记忆功能
java·spring·rag·springai
键盘帽子2 小时前
长连接中异步任务的同步等待陷阱:一次主线程阻塞的排查与修复
java·websocket·java-ee·web
你刷碗2 小时前
基于S32K144 CESc生成随机数
android·java·数据库
灰子学技术2 小时前
性能分析工具比较pprof、perf、valgrind、asan
java·开发语言
木井巳2 小时前
【多线程】单例模式
java·单例模式·java-ee