fix(file-service): use AntPathRequestMatcher to bypass Spring MVC matching

Spring Security 6 with MVC on classpath resolves requestMatchers(HttpMethod, String)
to MvcRequestMatcher, which fails to match the actual servlet paths for this service.
Switching to explicit AntPathRequestMatcher instances bypasses MVC introspection and
forces pure Ant pattern evaluation, fixing persistent 401 on public upload/serve endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-05-18 15:40:11 +08:00
父节点 b49b67bb1e
当前提交 8bc9b1ebda

查看文件

@ -5,13 +5,13 @@ import com.xuqm.common.security.JwtUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@ -35,13 +35,11 @@ public class SecurityConfig {
.cors(cors -> {})
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// Public: file upload and serving (AntRequestMatcher via explicit method)
.requestMatchers(HttpMethod.POST, "/api/file/upload").permitAll()
.requestMatchers(HttpMethod.GET, "/api/file/*/thumbnail").permitAll()
.requestMatchers(HttpMethod.GET, "/api/file/*").permitAll()
// Actuator health & info
.requestMatchers(HttpMethod.GET, "/actuator/**").permitAll()
.requestMatchers(new AntPathRequestMatcher("/**", "OPTIONS")).permitAll()
.requestMatchers(new AntPathRequestMatcher("/api/file/upload", "POST")).permitAll()
.requestMatchers(new AntPathRequestMatcher("/api/file/*/thumbnail", "GET")).permitAll()
.requestMatchers(new AntPathRequestMatcher("/api/file/*", "GET")).permitAll()
.requestMatchers(new AntPathRequestMatcher("/actuator/**", "GET")).permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(ex -> ex