Java案例如何生成Token令牌?

wen java案例 15

本文目录导读:

Java案例如何生成Token令牌?

  1. 使用JWT (JSON Web Token)
  2. 使用UUID生成简单Token
  3. Spring Boot完整示例
  4. 安全最佳实践
  5. 选择建议

我来介绍几种在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协议实现完整的认证授权方案。

抱歉,评论功能暂时关闭!