2025-01-30T16:46:27.928+04:00 ERROR 3173 --- [MyStoreAuth] [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
io.jsonwebtoken.ExpiredJwtException: JWT expired 170708927 milliseconds ago at 2025-01-28T13:21:19.000Z. Current time: 2025-01-30T12:46:27.927Z. Allowed clock skew: 0 milliseconds.
我不想在控制台中获得错误,并将我的自定义错误响应给用户。我试图通过在jwtauthfilter中丢弃错误并通过@RestControllerAdvice进行操作来做到这一点,但这行不通。我想问为什么当我从jwtauthfilter出现错误时它不起作用,但是我从控制器文件中抛出的其他错误会由 @restControllerAdvice.
处理。 我的代码是我的代码:
democontroller@RestController
@RequestMapping("/api/v1/demo")
public class DemoController {
@GetMapping("")
public ResponseEntity<String> sayHello() {
return ResponseEntity.ok("hi bro");
}
}
securityConfig
@Configuration
@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig {
private final AuthenticationProvider authenticationProvider;
private JwtAuthFilter jwtAuthFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("api/v1/auth/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}
globalexceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AuthenticationFailedException.class)
public ResponseEntity<ErrorResponse> handleAuthenticationFailedExceptions(AuthenticationFailedException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
"Authentication Failed",
ex.getMessage()
);
return new ResponseEntity<>(errorResponse, HttpStatus.UNAUTHORIZED);
}
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ErrorResponse> handleBadRequestExceptions(BadRequestException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Bad Request",
ex.getMessage()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Bad Request",
Objects.requireNonNull(ex.getBindingResult().getFieldError()).getDefaultMessage()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(InvalidTokenException.class)
public ResponseEntity<ErrorResponse> handleInvalidTokenExceptions(InvalidTokenException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
"Unauthorized",
ex.getMessage()
);
return new ResponseEntity<>(errorResponse, HttpStatus.UNAUTHORIZED);
}
}
jwtauthfilter
@Component
@AllArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private AppUserService appUserService;
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwtToken;
final String userEmail;
if (authHeader == null || !authHeader.startsWith("Bearer")) {
filterChain.doFilter(request, response);
return;
}
jwtToken = authHeader.substring(7);
userEmail = jwtService.extractUsername(jwtToken);
if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.appUserService.loadUserByUsername(userEmail);
try {
jwtService.isTokenValid(jwtToken, userDetails);
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
} catch (ExpiredJwtException e) {
throw new InvalidTokenException("Expired token");
} catch (JwtException e) {
throw new InvalidTokenException("Invalid token");
}
}
filterChain.doFilter(request, response);
}
}
jwtservice
@Service
public class JwtService {
public String extractUsername(String token) {
Claims claims = extractAllClaims(token);
return claims.getSubject();
}
public Date extractExpiration(String token) {
Claims claims = extractAllClaims(token);
return claims.getExpiration();
}
public String generateToken(UserDetails userDetails) {
return generateToken(new HashMap<>(), userDetails);
}
public String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {
return Jwts
.builder()
.claims(extraClaims)
.subject(userDetails.getUsername())
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 24))
.signWith(getSignInKey(), Jwts.SIG.HS256)
.compact();
}
public boolean isTokenValid(String token, UserDetails 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 Claims extractAllClaims(String token) {
return Jwts
.parser()
.verifyWith(getSignInKey())
.build()
.parseSignedClaims(token)
.getPayload();
}
private SecretKey getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
return Keys.hmacShaKeyFor(keyBytes);
}
}
过滤器执行前后
请求将传递给Spring和您的控制器,并且给定过滤器结束时,它永远不会由Spring或您的控制器处理,因此控制器建议永远不会发挥作用。