以下代码中,为什么要验证两次"token"?
if (JwtUtil.validateToken(authToken) && sessionService.isTokenValid(authToken)) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
}
因为 validateToken
和 isTokenValid
执行的是不同类型的验证,因此两者都是有其必要性的。下面是各自方法的功能解析:
-
validateToken(String token)
:- 这个方法使用
Jwts.parserBuilder()
来验证 JWT 令牌的结构、签名、有效性(例如是否过期)。这是基本的 JWT 安全性验证,确保了令牌在技术层面上是合法的。 - 如果令牌解析成功,说明它至少在创建时是由合法的服务生成,并且在传输过程中没有被篡改。
- 这个方法使用
-
isTokenValid(String token)
:- 这个方法通过查询 Redis 来检查令牌是否存在。这通常用于实现如会话管理的额外逻辑,例如检查用户是否已经登出或令牌是否被服务端主动废弃。
- 使用 Redis 进行检查可以帮助实现例如可撤销令牌的功能,即使令牌从技术上看仍然是有效的,也可以因为某些业务逻辑(如用户主动登出)而被标记为无效。
结论:
- 两次验证都是必要的。第一次验证确保了 JWT 本身的有效性和完整性。第二次验证则提供了对业务规则的支持,例如允许从服务端废弃或撤销令牌。
- 这种验证方式提高了系统的安全性,使得即便是技术上有效的令牌,也可以因为业务需求(如用户行为)而被标记为无效。
因此,这两种验证方法各自承担了不同的角色,共同提供了更全面的安全保障。维持这两步验证可以确保系统既能防范技术层面的攻击,也能满足业务层面的安全需求。