使用hashMap封装token工具类,并实现删除过期token和验证token

本文介绍了一种基于Java的Token管理机制,包括Token的生成、存储、验证及过期处理。通过使用HashMap存储Token信息,实现用户身份验证,并提供两种验证方式:带userId和不带userId的验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

final public class TokenUtils {

    public static long EXPIRY_TIME = 1000*60*30;//过期时间30分钟
    public static Map<String,Object> tokenMap = new HashMap<>();

    /**
     * 用userId添加token
     */
    public static void putTokenMap(String userId){
        Map<String,Object> tokenInfo = new HashMap<>();
        tokenInfo.put("token",UUID.randomUUID().toString());
        tokenInfo.put("expiryTime",System.currentTimeMillis()+EXPIRY_TIME);
        tokenMap.put(userId,tokenInfo);
    }

    /**
     * 删除过期token
     */
    public static void deleteExpiryToken(){
        Iterator<Map.Entry<String, Object>> iterator = tokenMap.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Object> next = iterator.next();
            Map<String,Object> tokenInfo = (Map<String,Object>)next.getValue();
            if ((long)tokenInfo.get("expiryTime")<System.currentTimeMillis()){
                iterator.remove();
            }
        }
    }

 	/**
     * 验证token(有userId)
     */
    public static Boolean checkToken(String token,String userId){
        //调用时遍历,删除已过期的token
        deleteExpiryToken();

        Iterator<Map.Entry<String, Object>> iterator = tokenMap.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Object> next = iterator.next();
            Map<String,Object> tokenInfo = (Map<String,Object>)next.getValue();
            if (tokenInfo.get("token").equals(token)&&next.getKey().equals(userId)){
                return true;
            }
        }
        return false;
    }

    /**
     * 验证token(无userId)
     */
    public static Boolean checkToken(String token){
        //调用时遍历,删除已过期的token
        deleteExpiryToken();

        Iterator<Map.Entry<String, Object>> iterator = tokenMap.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Object> next = iterator.next();
            Map<String,Object> tokenInfo = (Map<String,Object>)next.getValue();
            if (tokenInfo.get("token").equals(token)){
                return true;
            }
        }
        return false;
    }
}

在controller调用,也可以在filter中调用

	@RequestMapping("/getToken")
	public Map<String, Object> getToken(String userId) {
		TokenUtils.putTokenMap(userId);
		return (Map<String, Object>)TokenUtils.tokenMap.get(userId);
	}
	
	@RequestMapping("/checkToken")
	public Boolean checkToken(String token) {
		return TokenUtils.checkToken(token);
	}
### 如何使用JWT实现基于Token的登录验证结合Redis进行会话管理 #### 背景介绍 JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在网络应用环境间安全地传输信息。它通常被用来作为用户的身份凭证,在客户端服务端之间传递数据[^1]。 为了提高性能安全性,可以将 Redis 集成到 JWT 流程中。Redis 提供了高效的键值存储功能,能够快速存取用户的刷新令牌 (Refresh Token),通过设置过期时间来自动清理不再使用的令牌[^2]。 --- #### 技术架构概述 整个流程涉及以下几个核心部分: 1. **JWT生成**:服务端在用户成功登录后生成一个访问令牌 (Access Token) 一个刷新令牌 (Refresh Token)。 2. **Redis存储**:将 Refresh Token 存入 Redis 中,为其设定合理的过期时间。 3. **Token验证**:每次请求时,服务端会对 Access Token 进行解码签名验证;如果 Access Token 已经过期,则尝试通过 Refresh Token 获取新的 Access Token。 4. **安全性保障**:通过对 Refresh Token 设置严格的生命周期管理签名算法,防止恶意攻击者伪造或篡改令牌。 --- #### 示例代码 以下是基于 Java 的示例代码,展示如何实现上述逻辑: ##### 1. 添加依赖项 确保项目引入必要的库文件,例如 `jose4j`(用于处理 JWT)、`spring-boot-starter-data-redis`(用于操作 Redis)等。 ```xml <dependency> <groupId>org.jose4j</groupId> <artifactId>jose4j</artifactId> <version>0.7.11</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` --- ##### 2. 创建工具类以生成解析 JWT ```java import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.consumer.InvalidJwtException; import org.jose4j.jwt.consumer.JwtConsumer; import org.jose4j.jwt.consumer.JwtConsumerBuilder; public class JwtUtil { private static final String SECRET_KEY = "your_secret_key"; // 替换为实际密钥 public static String generateAccessToken(String userId) { JwtClaims claims = new JwtClaims(); claims.setSubject(userId); claims.setExpirationTimeMinutesInTheFuture(15); // 访问令牌有效期设为15分钟 return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact(); } public static boolean validateAccessToken(String token) throws InvalidJwtException { JwtConsumer consumer = new JwtConsumerBuilder() .setRequireExpirationTime() // 验证是否设置了过期时间 .setMaxFutureValidityInMinutes(1) // 允许的最大未来有效时间为1分钟 .setAllowedClockSkewInSeconds(30) // 允许的时间偏移量为30秒 .setVerificationKey(SECRET_KEY.getBytes()) // 使用相同的密钥进行签名验证 .build(); try { consumer.processToClaims(token); return true; // 如果没有抛出异常则表示验证成功 } catch (InvalidJwtException e) { throw e; // 将错误向上层抛出以便进一步处理 } } } ``` --- ##### 3. 利用 Redis 存储 Refresh Token 配置 Redis 数据源连接参数,定义相关方法完成对 Refresh Token 的增删查改操作。 ```java @Service public class RedisService { @Autowired private StringRedisTemplate redisTemplate; public void saveRefreshToken(String key, String value, long timeout, TimeUnit unit) { ValueOperations<String, String> ops = redisTemplate.opsForValue(); ops.set(key, value, timeout, unit); } public Boolean existsRefreshToken(String key) { return redisTemplate.hasKey(key); } public String getRefreshToken(String key) { ValueOperations<String, String> ops = redisTemplate.opsForValue(); return ops.get(key); } public void deleteRefreshToken(String key) { redisTemplate.delete(key); } } ``` --- ##### 4. 用户登录接口实现 当用户提交用户名密码组合至服务器端校验无误之后返回两个类型的 Tokens 给前端保存起来备用。 ```java @RestController @RequestMapping("/auth") public class AuthController { @Autowired private UserService userService; @PostMapping("/login") public ResponseEntity<Map<String, Object>> login(@RequestBody LoginRequest request) { User user = userService.authenticate(request.getUsername(), request.getPassword()); if(user != null){ Map<String,Object> response=new HashMap<>(); // Generate tokens here... String accessToken=JwtUtil.generateAccessToken(user.getId()); String refreshToken=UUID.randomUUID().toString(); // Save refresh token into REDIS with expiration time set to one week. redisService.saveRefreshToken(refreshToken,user.getId(),7,TimeUnit.DAYS); response.put("access_token",accessToken); response.put("refresh_token",refreshToken); return new ResponseEntity<>(response,HttpStatus.OK); }else{ return new ResponseEntity<>("Bad Credentials!", HttpStatus.UNAUTHORIZED); } } } ``` --- #### 总结说明 以上展示了完整的从理论概念到具体实践的过程,包括但不限于 JWT 的创建、解析及其与 Redis 结合运用等方面的知识点。这种设计方案不仅简化了传统 Session 基础上的状态维护方式,还极大地增强了系统的扩展性灵活性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值