Spring Security 由于iat和exp日期,无法测试JWT令牌的generateToken()方法

u5rb5r59  于 2023-08-05  发布在  Spring
关注(0)|答案(1)|浏览(116)

我想测试我的JwtService,它是用来生成和处理JWT Token的。我甚至不确定,如果我必须测试它,因为不是所有的方法都是我的,但我仍然想看看令牌是否正确生成。但是,如果我想测试生成的令牌是否正确,我必须将其与另一个令牌进行比较。唯一的问题是时间差,所以iat(Issued At)和exp(Expiration Time/Date)是不同的。这就是为什么测试总是失败。即使iat和exp不同,我如何进行测试?

JwtService:

package de.gabriel.vertretungsplan.security.service;

import de.gabriel.vertretungsplan.models.UserDetailsImpl.UserDetailsImpl;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Service;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Service
public class JwtService {

    /*
    Generated with: https://www.allkeysgenerator.com/; 256-bit key
     */
    private static final String SECRET_KEY = "secret_key";

    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    public String generateToken(UserDetailsImpl userDetails) {
        return generateToken(new HashMap<>(), userDetails);
    }

    public String generateToken(
            Map<String, Object> extraClaims,
            UserDetailsImpl userDetails
    ) {
        return Jwts.builder()
                .setClaims(extraClaims)
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 7))) // 7 days
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    public boolean isTokenValid(String token, UserDetailsImpl userDetails) {
        final String username = extractUsername(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }

    private boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    private Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    private Claims extractAllClaims(String token) {
        return Jwts
                .parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    private Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
    }

}

字符串
这就是我想要测试它的方式:

@Test
public void generateToken_shouldGenerateToken() {
    Verwaltung verwaltung = new Verwaltung(
            "user",
            "user@gmail.com",
            "user",
            Rolle.getPrefixedRolle(Rolle.USER)
    );
    String generatedToken = jwtService.generateToken(new UserDetailsImpl(verwaltung));
    assertEquals(token, generatedToken);
}


预期的token是在www.example.com上生成jwt.io,具有与参考/预期令牌相同的密钥和所有内容。有没有人知道如何测试它,即使有时间差?

8dtrkrch

8dtrkrch1#

您可以采用不同的方法,验证JWT的内容,而不是将其与预生成的令牌进行比较(其中包含时间戳(iat和exp字段),因此它始终与预生成的令牌不同):

@Test
public void generateToken_shouldGenerateToken() {
    Verwaltung verwaltung = new Verwaltung(
            "user",
            "user@gmail.com",
            "user",
            Rolle.getPrefixedRolle(Rolle.USER)
    );
    String generatedToken = jwtService.generateToken(new UserDetailsImpl(verwaltung));

    // parse generated token
    Claims claims = Jwts.parser()
                        .setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY))
                        .parseClaimsJws(generatedToken)
                        .getBody();

    assertEquals(verwaltung.getUsername(), claims.getSubject());
    // check if the token is not expired
    assertFalse(claims.getExpiration().before(new Date()));
}

字符串

相关问题