Spring 容器初始化時有打印出 JWT Secret 的值,但在實際調用時 base64Secret() 卻是 null

@Configuration
public class FilterConfig {

    // 配置和注册自定义过滤器,用于拦截和处理特定路径的请求
    @Bean
    public FilterRegistrationBean<ServiceFilter> userTrackingFilter(ServiceFilter filter) {
        FilterRegistrationBean<ServiceFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(filter);
//        registrationBean.setFilter(new ServiceFilter(jwtProvider));
        registrationBean.addUrlPatterns("/api/v1/cry/**");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}
@Slf4j
@Component
public class JwtProvider {

    @Value("${jwt.secret}")
    private String base64Secret;

    @Value("${jwt.ttl}")
    private long jwtExpiration;

    @PostConstruct
    public void init() {
        log.info("JwtProvider initialized, base64Secret: {}", base64Secret);
        if (base64Secret == null || base64Secret.isEmpty()) {
            throw new RuntimeException("JWT Secret 未正確讀取!");
        }
    }

    @PreDestroy
    public void destroy() {
        log.info("JwtProvider being destroyed, base64Secret: {}", base64Secret);
    }

    public Key getBase64Secret() {
        try {
            log.info("JwtProvider base64Secret:{}",base64Secret);
            byte[] decodedKey = Base64.getDecoder().decode(base64Secret);
//            log.info("decodedKey:{}",decodedKey);
            return Keys.hmacShaKeyFor(decodedKey);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("JWT Secret 格式錯誤,請確保是 Base64 編碼", e);
        }
    }
package com.feddoubt.Cry.filter;

import com.feddoubt.common.Cry.config.jwt.JwtProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) //  正確方式關閉 CSRF
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/v1/auth/login", "/api/v1/auth/token", "/api/v1/key/public").permitAll() // 允許這些路徑不需要認證
                        .anyRequest().authenticated() // 其他 API 需要驗證
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 無狀態,使用 JWT
                .addFilterBefore(new ServiceFilter(new JwtProvider()), UsernamePasswordAuthenticationFilter.class); // 加入 JWT 過濾器

        return http.build();
    }
}

.addFilterBefore(new ServiceFilter(new JwtProvider()) 這裡手動 new 了一個 JwtProvider 實例,這個新建的實例不是由 Spring 容器管理的,所以 @Value 注入就不會生效,導致 base64Secret 為 null。

修改後

package com.feddoubt.Cry.filter;

import com.feddoubt.common.Cry.config.jwt.JwtProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    private final JwtProvider jwtProvider;
    private final ServiceFilter serviceFilter;

    public SecurityConfig(JwtProvider jwtProvider, ServiceFilter serviceFilter) {
        this.jwtProvider = jwtProvider;
        this.serviceFilter = serviceFilter;
    }


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) //  正確方式關閉 CSRF
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/v1/auth/login", "/api/v1/auth/token",  "/api/v1/key/public").permitAll() // 允許這些路徑不需要認證
                        .anyRequest().authenticated() // 其他 API 需要驗證
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 無狀態,使用 JWT
                .addFilterBefore(serviceFilter, UsernamePasswordAuthenticationFilter.class); // 加入 JWT 過濾器

        return http.build();
    }
}