我一直在努力与令牌刷新与Spring Boot 安全。
在此之前,我已经完成了与JWT的工作身份验证,但现在当我创建这个刷新系统时,它再也无法登录了。说“JWT签名与本地计算的签名不匹配。JWT有效性无法Assert,不应被信任。"。我试图通过在这里找到的不同主题和从Google找到的不同主题解决这个问题。
现在,我不能理解这种情况下,错误来自哪里.我崩溃的JWT验证方法:
JwtUtils.java
package com.testapp.springbooot.security.jwt;
import java.security.Key;
import java.util.Date;
import com.testapp.springbooot.security.services.UserDetailsImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
@Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
@Value("${testapp.app.jwtSecret}")
private String jwtSecret;
@Value("${testapp.app.jwtExpirationMs}")
private int jwtExpirationMs;
public String generateJwtToken(Authentication authentication) {
UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
return Jwts.builder()
.setId("" + userPrincipal.getId())
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(key(), SignatureAlgorithm.HS512)
.compact();
}
private Key key() {
return Keys.secretKeyFor(SignatureAlgorithm.HS512);
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getSubject();
}
public String getEmailFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getSubject();
}
public Date getExpirationFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getExpiration();
}
public String getUserIdFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getId();
}
public boolean isJWTExpired(String authToken) {
Date expiresAt = getExpirationFromJwtToken(authToken);
return expiresAt.before(new Date());
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parserBuilder().setSigningKey(key()).build().parse(authToken);
return true;
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}
字符串
以及登录认证控制器:
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getEmail(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream().map(item -> item.getAuthority())
.collect(Collectors.toList());
User completeUser = userRepository.findById(userDetails.getId()).orElseThrow(() -> new ObjectNotFoundException(userDetails.getId(), "user"));
RefreshToken refreshToken = refreshTokenService.createRefreshToken(userDetails.getId());
return ResponseEntity
.ok(new JwtResponse(jwt, refreshToken.getToken(), userDetails.getEmail(), roles, completeUser.getFirstName(), completeUser.getLastName(), completeUser.getHeight(), completeUser.getSex()));
}
型
我有恼人的头痛这个错误。只是找不到解决方案。尝试了几个解决方案找到,但不工作。仍然说同样的错误。
1条答案
按热度按时间ltskdhd11#
基本上,应该使用相同的键来生成JWT令牌并验证相同的JWT。
在令牌生成期间,您似乎使用了不同的密钥来对JWT进行签名(
generateJwtToken
)和验证(validateJwtToken
)。在generateJwtToken
中,您每次都使用Keys.secretKeyFor(SignatureAlgorithm.HS512)
生成新的密钥,而在validateJwtToken
中,您使用的是key()
,它使用相同的算法生成新的密钥。要解决此问题,你应该使用相同的密钥来进行签名和验证。实现这一点的一种方法是将密钥作为一个字段存储在你的JwtUtils组件中并重用它。