本文目录导读:

我来介绍几种在Java中生成Token令牌的常见方法:
使用JWT (JSON Web Token)
Maven依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
实现代码
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtTokenUtil {
// 生成密钥(生产环境应使用配置)
private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
private static final long EXPIRATION_TIME = 3600000; // 1小时
/**
* 生成Token
*/
public static String generateToken(String userId, String username) {
Date now = new Date();
Date expirationDate = new Date(now.getTime() + EXPIRATION_TIME);
Map<String, Object> claims = new HashMap<>();
claims.put("userId", userId);
claims.put("username", username);
claims.put("role", "USER");
return Jwts.builder()
.setClaims(claims)
.setSubject(userId)
.setIssuedAt(now)
.setExpiration(expirationDate)
.signWith(SECRET_KEY)
.compact();
}
/**
* 解析Token
*/
public static Claims parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody();
}
/**
* 验证Token是否有效
*/
public static boolean validateToken(String token) {
try {
Claims claims = parseToken(token);
return !claims.getExpiration().before(new Date());
} catch (Exception e) {
return false;
}
}
/**
* 从Token获取用户ID
*/
public static String getUserIdFromToken(String token) {
Claims claims = parseToken(token);
return claims.get("userId", String.class);
}
}
使用UUID生成简单Token
import java.util.UUID;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SimpleTokenGenerator {
/**
* 生成UUID Token
*/
public static String generateUUIDToken() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 生成带时间戳的Token
*/
public static String generateTimestampToken(String userId) {
String rawToken = userId + System.currentTimeMillis() + UUID.randomUUID().toString();
return encryptMD5(rawToken);
}
/**
* MD5加密
*/
private static String encryptMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
Spring Boot完整示例
配置类
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtConfig {
private String secretKey = "your-secret-key-at-least-256-bits-long";
private long expiration = 3600000; // 1小时
private String issuer = "your-app-name";
// getters and setters
}
Token服务类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
@Service
public class TokenService {
@Autowired
private JwtConfig jwtConfig;
private SecretKey getSecretKey() {
byte[] keyBytes = Base64.getDecoder().decode(
Base64.getEncoder().encodeToString(jwtConfig.getSecretKey().getBytes())
);
return new SecretKeySpec(keyBytes, "HmacSHA256");
}
public String generateToken(User user) {
Date now = new Date();
Date expiration = new Date(now.getTime() + jwtConfig.getExpiration());
return Jwts.builder()
.setSubject(user.getId().toString())
.claim("username", user.getUsername())
.claim("email", user.getEmail())
.setIssuer(jwtConfig.getIssuer())
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(getSecretKey())
.compact();
}
}
控制器
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private TokenService tokenService;
@PostMapping("/login")
public Map<String, Object> login(@RequestBody LoginRequest request) {
// 验证用户名密码(实际应该从数据库查询)
if ("admin".equals(request.getUsername()) && "123456".equals(request.getPassword())) {
User user = new User();
user.setId(1L);
user.setUsername(request.getUsername());
user.setEmail("admin@example.com");
String token = tokenService.generateToken(user);
Map<String, Object> result = new HashMap<>();
result.put("token", token);
result.put("type", "Bearer");
result.put("expiresIn", "3600");
return result;
}
throw new RuntimeException("用户名或密码错误");
}
}
应用配置 (application.yml)
jwt: secret-key: your-secure-secret-key-at-least-256-bits-long expiration: 86400000 # 24小时 issuer: my-application
安全最佳实践
public class TokenSecurityBestPractices {
// 1. Token刷新机制
public TokenPair generateTokenWithRefresh(User user) {
String accessToken = generateAccessToken(user);
String refreshToken = generateRefreshToken(user);
return new TokenPair(accessToken, refreshToken);
}
private String generateAccessToken(User user) {
// 短有效期(15分钟)
return Jwts.builder()
.setSubject(user.getId().toString())
.setExpiration(new Date(System.currentTimeMillis() + 900000))
.signWith(getSecretKey())
.compact();
}
private String generateRefreshToken(User user) {
// 长有效期(7天)
return Jwts.builder()
.setSubject(user.getId().toString())
.setExpiration(new Date(System.currentTimeMillis() + 604800000))
.signWith(getRefreshKey())
.compact();
}
// 2. Token黑名单(用于登出)
private Set<String> blacklist = new HashSet<>();
public void invalidateToken(String token) {
blacklist.add(token);
}
public boolean isTokenBlacklisted(String token) {
return blacklist.contains(token);
}
// 3. Token包含设备信息
public String generateTokenWithDeviceInfo(User user, String deviceId, String ip) {
return Jwts.builder()
.setSubject(user.getId().toString())
.claim("deviceId", deviceId)
.claim("ip", ip)
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(getSecretKey())
.compact();
}
}
选择建议
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| JWT | 分布式系统、微服务 | 无状态、可携带信息 | Token大小较大 |
| UUID | 简单场景、临时令牌 | 实现简单、唯一性好 | 不可携带信息 |
| Session Token | 单体应用 | 服务端可控 | 需要存储、扩展性差 |
推荐在大多数现代Web应用中使用JWT,配合OAuth2.0协议实现完整的认证授权方案。