要在 Spring Boot 里实现接口统一拦截并校验 Token,可以借助 Spring 的拦截器机制。下面是具体的实现步骤和代码示例。
1. 创建 Token 工具类
java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
public class TokenUtils {
// 密钥,可根据实际情况修改
private static final String SECRET_KEY = "yourSecretKey";
// Token 过期时间,单位为毫秒,这里设置为 1 小时
private static final long EXPIRATION_TIME = 1000 * 60 * 60;
// 生成 Token 的方法
public static String generateToken(String username) {
long timestamp = new Date().getTime();
String data = username + ":" + timestamp;
String hash = hashData(data + SECRET_KEY);
return data + ":" + hash;
}
// 校验 Token 的方法
public static boolean validateToken(String token, String username) {
String[] parts = token.split(":");
if (parts.length != 3) {
return false;
}
String storedUsername = parts[0];
long timestamp = Long.parseLong(parts[1]);
String storedHash = parts[2];
// 检查用户名是否匹配
if (!storedUsername.equals(username)) {
return false;
}
// 检查 Token 是否过期
if (new Date().getTime() - timestamp > EXPIRATION_TIME) {
return false;
}
// 重新计算哈希值并比较
String data = storedUsername + ":" + timestamp;
String newHash = hashData(data + SECRET_KEY);
return newHash.equals(storedHash);
}
// 哈希处理方法
private static String hashData(String data) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] encodedHash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encodedHash);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}
2. 创建 Token 拦截器
java
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头中获取 Token
String token = request.getHeader("Authorization");
// 这里简单假设用户名在请求参数中,实际应用中可根据需求调整
String username = request.getParameter("username");
if (token == null || username == null) {
sendErrorResponse(response, "Token or username is missing");
return false;
}
if (!TokenUtils.validateToken(token, username)) {
sendErrorResponse(response, "Invalid Token");
return false;
}
return true;
}
private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.write("{\"error\": \"" + message + "\"}");
writer.flush();
writer.close();
}
}
3. 配置拦截器
java
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 WebConfig implements WebMvcConfigurer {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/login"); // 排除登录接口
}
}
4. 控制器示例
java
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class AuthController {
@PostMapping("/login")
public Map<String, String> login(@RequestBody Map<String, String> credentials) {
String username = credentials.get("username");
String password = credentials.get("password");
// 这里可以添加用户名和密码的验证逻辑
if ("yourUsername".equals(username) && "yourPassword".equals(password)) {
String token = TokenUtils.generateToken(username);
Map<String, String> response = new HashMap<>();
response.put("token", token);
return response;
} else {
return new HashMap<>();
}
}
@PostMapping("/test")
public String test() {
return "Token validation passed";
}
}
代码解释
- TokenUtils 类:负责生成和校验 Token。
- TokenInterceptor 类 :实现了
HandlerInterceptor
接口,在preHandle
方法中对请求进行拦截,从请求头中获取 Token,从请求参数中获取用户名,调用TokenUtils
类的validateToken
方法进行校验。若校验不通过,返回错误响应。 - WebConfig 类 :实现了
WebMvcConfigurer
接口,在addInterceptors
方法中配置拦截器,拦截所有请求,但排除登录接口。 - AuthController 类 :包含登录接口
/login
和测试接口/test
,登录接口用于生成 Token,测试接口用于验证 Token 校验是否生效。
通过以上步骤,就能在 Spring Boot 中实现接口统一拦截并校验 Token。