【问题标题】:JWT logout on Spring MVCSpring MVC 上的 JWT 注销
【发布时间】:2018-09-23 20:02:34
【问题描述】:

我有一个小问题要解决,我写了一个用于生成和验证 JWT 令牌的类,但我走到了一个十字路口:如何使令牌无效以实现注销功能?使用 Spring MVC 创建简单的 API rest 以与 Angular 5 中的外部前端进行交互。

代码:

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;

@SuppressWarnings("restriction")
public class SecurityUtil {

    private static final String secretKey = "secret";
    private static final Logger logger =  LoggerFactory.getLogger(SecurityUtil.class);
    private static Clock clock = DefaultClock.INSTANCE;

    public static PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    private static Date getExpirationDateFromToken(String token) {
         Claims claims = getAllClaimsFromToken(token);
         if(claims != null) {
             return claims.getExpiration();
         }
         return null;
    }

    private static Claims getAllClaimsFromToken(String token) {
        try {
             return Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(secretKey))
                    .parseClaimsJws(token)
                    .getBody();
        }catch(Exception ex) {
            logger.info(ex.getMessage());
            return null;
        }  
    }

    private static Boolean isTokenExpired(String token) {
        Date expiration = getExpirationDateFromToken(token);
        if(expiration != null) {
            return expiration.before(clock.now());
        }
        return null;

    }

    private static Date calculateExpirationDate(Date createdDate) {
        return new Date(createdDate.getTime() + (60 * 15) * 1000);
    }

    public static Boolean validateToken(String token) {
        try {
            return !isTokenExpired(token);
        }catch(Exception ex) {
            return false;
        }
    }

    public static String generateToken(String id, String subject) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        Date createdDate = clock.now();
        Date expirationDate = calculateExpirationDate(createdDate);

        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secretKey);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        return  Jwts.builder()
                .setId(id)
                .setIssuedAt(createdDate)
                .setSubject(subject)
                .signWith(signatureAlgorithm, signingKey)
                .setExpiration(expirationDate)
                .compact();

        }

    public static String refreshToken(String token) {
        Date createdDate = clock.now();
        Date expirationDate = calculateExpirationDate(createdDate);

        final Claims claims = getAllClaimsFromToken(token);
        claims.setIssuedAt(createdDate);
        claims.setExpiration(expirationDate);

        return Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS512, DatatypeConverter.parseBase64Binary(secretKey))
            .compact();
    }


}

我还注意到,在我刷新令牌后,过去的令牌并没有失效。

有人可以帮助我吗?

提前致谢

【问题讨论】:

    标签: java rest api spring-mvc jwt


    【解决方案1】:

    您对 JWT 的选择确实有限,因为它是一个无状态令牌,应该保存在客户端而不是服务器上,因此不能轻易失效。当然,您可以为服务器上的无效令牌添加自定义黑名单,但此解决方案无法很好地扩展,因为您需要将黑名单分发到所有应用程序实例(您可以使用任何分布式缓存解决方案用于黑名单存储)。

    也就是说,如果你将它与令牌本身的短 TTL 结合起来,它可能仍然可以正常工作,因为你可以对黑名单实施非常积极的清理策略(因为保留条目是没有意义的黑名单的时间长于令牌 TTL),从而减少了您需要复制的数据量。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,但我无法解决。我将到期日期更改为 2 分钟

      【讨论】:

        猜你喜欢
        • 2016-04-01
        • 2020-08-11
        • 1970-01-01
        • 2012-06-16
        • 1970-01-01
        • 2017-06-14
        • 2015-10-29
        • 2017-06-24
        • 2018-07-29
        相关资源
        最近更新 更多