Spring TestRestTemplate POST请求Basic Auth失效返回302问题
看起来你的GET接口用Basic Auth能正常测试,但POST接口却返回302重定向到登录页,我帮你梳理下几个大概率的原因和对应的解决办法:
1. POST请求缺少JSON格式请求头
你当前的POST测试代码里,构造HttpEntity时只传了请求体,没有指定Content-Type: application/json。而控制器的@PostMapping配合@RequestBody是期望接收JSON格式请求的,Spring如果无法解析请求体,可能会触发异常,进而被安全过滤器拦截导致重定向。
修改测试代码,加上正确的请求头:
@Test void filteredSearch() { // 构造JSON请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // 组装带请求头的请求实体 HttpEntity<FilteredSearchRequest> requestEntity = new HttpEntity<>(new FilteredSearchRequest(), headers); val reply = testRestTemplate.withBasicAuth("test", "test") .exchange("/reference_data/search", HttpMethod.POST, requestEntity, new ParameterizedTypeReference<List<Map<String, Object>>>() {}); System.out.println(reply); assertEquals(HttpStatus.OK, reply.getStatusCode()); }
2. ADFS安全配置与测试环境内存用户冲突
你的AdfsSecurityConfiguration默认是开启的(matchIfMissing = true),而测试环境配置了spring.security.user的内存用户,这两者的认证逻辑可能存在冲突:
AdfsConfigurer大概率配置了ADFS相关的认证(比如OAuth2或SAML),而Basic Auth是Spring Security的默认内存认证,过滤器执行顺序可能导致POST请求时Basic Auth未被正确识别。
这里有两种解决思路:
思路一:测试时排除ADFS安全配置
在测试类上直接排除AdfsSecurityConfiguration,让Spring Security使用默认的内存认证:
@SpringBootTest @EnableAutoConfiguration(exclude = AdfsSecurityConfiguration.class) class YourControllerTest { // 你的测试代码... }
思路二:让ADFS配置兼容测试环境的Basic Auth
修改AdfsSecurityConfiguration,当处于test profile时,添加Basic Auth支持:
@Override protected void configure(final HttpSecurity http) throws Exception { if (!isRunningLocally()) { http.requiresChannel().anyRequest().requiresSecure(); } // 测试环境下启用Basic Auth if (environment.acceptsProfiles(Profiles.of("test"))) { http.httpBasic(); } http.apply(adfsConfigurer).and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().authorizeRequests() .requestMatchers(EndpointRequest.to("keepalive", "info", "health", "env"), EndpointRequest.toLinks()) .permitAll().anyRequest().authenticated().and().csrf().disable(); } // 同时更新本地环境判断,把test profile也包含进来 private boolean isRunningLocally() { return environment.acceptsProfiles(Profiles.of("default", "test")); }
3. 测试环境被强制要求HTTPS
你的isRunningLocally()方法只判断了default profile,但测试用的是test profile,所以这个方法会返回false,进而执行http.requiresChannel().anyRequest().requiresSecure();,强制所有请求使用HTTPS。而TestRestTemplate默认用HTTP请求,会被重定向,最终导致跳转到登录页。
解决办法就是把test profile加入本地环境的判断,让测试环境不强制HTTPS:
private boolean isRunningLocally() { return environment.acceptsProfiles(Profiles.of("default", "test")); }
内容的提问来源于stack exchange,提问作者Tejesh Raut

