【问题标题】:Test same token after rebuild app. JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted重建应用程序后测试相同的令牌。 JWT 签名与本地计算的签名不匹配。 JWT 有效性不能被断言,也不应该被信任
【发布时间】:2022-11-06 04:06:40
【问题描述】:

我在 REST 服务应用程序中工作并生成令牌并成功测试它。它可以工作,但是在重新运行应用程序后测试相同的令牌时,它会给我这个错误消息(JWT 签名与本地计算的签名不匹配。JWT 有效性不能被断言并且不应该被信任。--{})。 我认为每次关闭并运行应用程序时可能会更改 Java Key 中的问题并且找不到解决方案。

在这里,我使用 Postman 并生成访问令牌。

!

成功测试令牌。

!

重建项目后测试相同的令牌。

!

!

TokenUtils 类用于生成访问令牌和验证。

package com.keroles.jobify.Sec.Token.Util;

import com.keroles.jobify.Sec.Token.Model.TokenModel;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
@Getter
public class TokenUtils {
    private final long ACCESS_TOKEN_VALIDITY=432000L;//7days
    private final long REFRESH_TOKEN_VALIDITY=604800L;//7days
    @Getter(AccessLevel.NONE)
    private final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);


    public String generateToken(Authentication authentication ,long validityTime){
 log.error("{}",key.getEncoded());
 log.error(key.getEncoded().toString());
 return Jwts
                .builder()
                .setClaims(prepareClaims(authentication))
                .setSubject(authentication.getName())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis()
                        + validityTime * 1000))
                .signWith(key)
                .compact();
    }


    public TokenModel getTokenModel(String token){
        Claims claims= getAllClaimsFromToken(token);
        return TokenModel
                .builder()
                .username(claims.getSubject())
                .roles((List<String>)claims.get("roles"))
                .createdAt(new Date( (Long) claims.get("created")))
                .expirationDate(claims.getExpiration())
                .build();
    }

    public boolean validateToken(TokenModel tokenModel, UserDetails userDetails){
        return (userDetails!=null
                && tokenModel.getUsername().equals(userDetails.getUsername())
                && ! isTokenExpired(tokenModel.getExpirationDate()));
    }

    private boolean isTokenExpired(Date expirationDate) {
        return expirationDate.before(new Date());
    }
    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
    }
    private Map<String,Object> prepareClaims(Authentication authentication){
        List<String>authority=authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        Map<String, Object> claims = new HashMap<>();
        claims.put("created",new Date());
        claims.put("roles",authority);
        return claims;
    }

【问题讨论】:

    标签: java spring-boot spring-security jwt postman


    【解决方案1】:

    每次启动应用程序时,您都会获得一个新密钥,相关部分来自docs

    公共静态 SecretKey secretKeyFor(SignatureAlgorithm alg) 抛出 IllegalArgumentException

    返回一个新的 SecretKey,其密钥长度适用于指定的 签名算法。 JWA 规范 (RFC 7518),第 3.2 节要求 用于每个相应签名的最小密钥长度 算法。此方法返回一个安全随机生成的 SecretKey 遵守所需的最小密钥长度。

    为了玩耍,您可以将纯文本秘密放入您的属性文件中,并为生产选择以下选项之一:https://stackoverflow.com/questions/37404703/spring-boot-how-to-hide-passwords-in-properties-file. 从属性文件加载密码后,更改签名和解析以使用您的密码。签名示例:

    return Jwts
                    .builder()
                    .setClaims(prepareClaims(authentication))
                    .setSubject(authentication.getName())
                    .setIssuedAt(new Date(System.currentTimeMillis()))
                    .setExpiration(new Date(System.currentTimeMillis()
                            + validityTime * 1000))
                    .signWith(SignatureAlgorithm.HS256, injectedSecretFromProperties)
                    .compact();
    

    【讨论】:

      猜你喜欢
      • 2019-10-31
      • 2020-08-30
      • 2017-07-12
      • 2021-03-26
      • 2018-03-16
      • 2017-05-30
      • 2017-10-15
      • 2016-12-25
      • 2016-11-17
      相关资源
      最近更新 更多