在 Spring Boot 里,即便不添加额外依赖,也能手动生成和校验 Token。下面以简单的基于时间戳和密钥的方式来生成和校验 Token 为例,介绍具体实现步骤。
实现思路
- 生成 Token:把用户信息、时间戳等数据组合起来,再用密钥进行哈希处理,生成一个唯一的 Token。
- 校验 Token:从 Token 里提取出用户信息和时间戳,重新进行哈希处理,然后与原 Token 进行对比,同时检查时间戳是否过期。
代码实现
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.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("/validate")
public Map<String, Boolean> validate(@RequestBody Map<String, String> request) {
String token = request.get("token");
String username = request.get("username");
boolean isValid = TokenUtils.validateToken(token, username);
Map<String, Boolean> response = new HashMap<>();
response.put("isValid", isValid);
return response;
}
}
代码解释
- TokenUtils 类 :
generateToken
方法:把用户名和时间戳组合起来,再加上密钥进行哈希处理,生成 Token。validateToken
方法:从 Token 里提取用户名、时间戳和哈希值,检查用户名是否匹配、Token 是否过期,重新计算哈希值并与原哈希值进行比较。hashData
方法:使用 SHA - 256 算法对数据进行哈希处理,并将结果进行 Base64 编码。
- AuthController 类 :
login
方法:模拟用户登录,验证用户名和密码,若验证通过则生成 Token 并返回。validate
方法:接收 Token 和用户名,调用TokenUtils
类的validateToken
方法进行校验,返回校验结果。
注意事项
- 此方法生成的 Token 安全性相对较低,在实际生产环境中,建议使用成熟的 JWT 库(如
jjwt
)来生成和校验 Token。 - 密钥
SECRET_KEY
要妥善保管,避免泄露。