【发布时间】:2020-12-31 13:55:26
【问题描述】:
我有一个项目,目前有一个启用多用户会话的功能。但是现在我想让它像新用户登录时那样,然后该用户的所有其他会话都将失效。用户认证基于 JWT Token。那么如何才能使该用户的所有现有 JWT 令牌失效而只保留新令牌呢?
注意:目前我没有将 JWT 令牌存储在数据库中,我不希望这样,因为它会泄露安全性。
这是 JWTTokenUtils 的类,我从中生成令牌并对其进行验证。
@Component
public class JwtTokenUtil implements Serializable {
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(Base64.getEncoder().encodeToString(Constants.JWTToken.SIGNING_KEY.getBytes()))
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public String generateToken(String userId) {
return doGenerateToken(userId);
}
private String doGenerateToken(String userId) {
Claims claims = Jwts.claims().setSubject(userId);
claims.put("scopes", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
return Jwts.builder()
.setClaims(claims)
.setId(userId)
.setIssuer(null)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_VALIDITY_SECONDS * 1000))
.signWith(SignatureAlgorithm.HS256, Base64.getEncoder().encodeToString(Constants.JWTToken.SIGNING_KEY.getBytes()))
.setHeaderParam("typ", "JWT")
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername())
&& !isTokenExpired(token));
}
}
【问题讨论】:
-
您不能使 JWT 的设计失效不是事实吗?您说您不想将它们存储在数据库中,因为“泄露安全性”,您能详细说明一下吗?许多应用程序都使用这种方法,而不会产生重大的安全隐患。
-
该项目已获得 PCI 安全标准委员会的保护和认证,为了匹配和遵循标准,我们无法存储它。
-
您是否可以在 JWT 令牌中没有会话 ID,您确实存储了该会话 ID,并且当您想要使令牌无效时可以从数据库中删除?
-
或者只为每个用户存储一个日期,并忽略在该日期之前发布的任何 JWT 令牌,即使它们尚未过期。
-
@tgdavies 最好不要将会话 ID 与 JWT 恕我直言混合。此外,使用缓存而不是数据库来存储此类状态(数据库不会很好地扩展)。
标签: java spring-boot authentication jwt jwt-auth