java:如何使特定用户的所有jwt令牌失效?

7hiiyaii  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(788)

我有一个项目,目前有一个功能,其中多用户会话是启用的。但是现在我想让它成为一个新用户登录时,该用户的所有其他会话都将无效。用户身份验证基于jwt令牌。那么,如何使该用户的所有现有jwt令牌失效,而只保留新的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));
    }
}
llew8vvj

llew8vvj1#

为了做到这一点,你基本上需要在某个地方保持某种状态。您可能会考虑的一种通用方法是维护应该被阻止的用户的黑名单缓存。在您的特定情况下,还可以存储与每个用户关联的日期。对于每个传入的请求,您首先要快速命中黑名单缓存,并确保传入jwt的日期不太旧。当然,你可以Assert exp 声明,因为可能传入的jwt在第一时间就已经过期了。
这里的关键点是使用缓存,比如redis,它有非常快速的查找。您也可以使用数据库,但这将比一个好的缓存工具慢大约100倍。关于修剪缓存,当用户不再需要旧的jwt状态时,您可以删除他的条目。这可以通过在写缓存条目时为其指定一个到期日来实现自动化。

相关问题