Код: Выделить всё
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthRestController {
private final PaymentService paymentService;
@PostMapping("/token")
public String generateToken(@RequestBody TokenRequest request) throws Exception {
return paymentService.createToken(request);
}
}
@Slf4j
@RequiredArgsConstructor
public class RedisJwtAuthenticationFilter extends OncePerRequestFilter {
private final PaymentSessionService paymentSessionService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String txn = request.getHeader("X-Transaction-Id");
log.info("FILTER THREAD = {}", Thread.currentThread().getName());
if (StringUtils.isNotBlank(txn)) {
if (!paymentSessionService.sessionExists(txn)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
}
filterChain.doFilter(request, response);
}
}
public boolean sessionExists(final String txn) {
log.info("REDIS THREAD = {}", Thread.currentThread().getName());
final String key = ENDA_TXN + txn;
try {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
} catch (DataAccessException e) {
throw new RedisUnavailableException("Redis is unavailable while checking the session", e);
}
}
@Bean
@Order(2)
public SecurityFilterChain filterChain(HttpSecurity http,
ApplicationProperties applicationProperties,
AesGcmJwtDecoder aesGcmJwtDecoder,
JwtAuthenticationConverter jwtAuthenticationConverter,
RedisJwtAuthenticationFilter redisJwtAuthenticationFilter) throws Exception {
http
.cors(withDefaults())
.csrf(AbstractHttpConfigurer::disable)
.addFilterAfter(redisJwtAuthenticationFilter, SecurityContextHolderFilter.class)
.headers(headers ->
headers
.contentSecurityPolicy(csp -> csp.policyDirectives(applicationProperties.getSecurity().getContentSecurityPolicy()))
.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
.referrerPolicy(referrer -> referrer.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN))
.permissionsPolicyHeader(permissions ->
permissions.policy("camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()")
)
)
.authorizeHttpRequests(authz -> authz
.anyRequest().authenticated()
)
.sessionManagement(mgmt -> mgmt.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.decoder(aesGcmJwtDecoder)
.jwtAuthenticationConverter(jwtAuthenticationConverter)
)
);
return http.build();
}
2025-11-19 09:47:31.611 [traceId: a5dba50bef617c87a]
[http-nio-9008-exec-3] AuthRestController — завершить выполнение
2025-11-19 09:47:31.629 [traceId: c2aa664e25e67da2]
[http-nio-9008-exec-4] RedisJwtAuthenticationFilter - ФИЛЬТРАЦИЯ ПОТОКА
Как вы можете см.:
Контроллер выполняется на http-nio-9008-exec-3
Фильтр выполняется на http-nio-9008-exec-4
Из-за этого изменения потока Micrometer генерирует новый идентификатор трассировки, и я не могу отслеживать транзакцию в журналах.
Примечания:
Я использую Jedis/StringRedisTemplate в фильтре (синхронный, блокирующий)
Я не использую @Async или CompletableFuture
Вызовы WebClient обрабатываются .block()
У меня также есть @EnableAspectJAutoProxy(proxyTargetClass = true), но я не думаю, что это вызывает это
Вопрос:
Почему поток между контроллером и моим фильтром в Tomcat меняется?
Как сохранить один и тот же поток (или передать один и тот же идентификатор трассировки) через фильтр и контроллер для правильной трассировки?
Подробнее здесь: https://stackoverflow.com/questions/798 ... -in-spring
Мобильная версия