Spring Boot回调uri含本地8080端口时被重写为Host头值问题排查
问题原因
该URL重写行为是Spring Web(Spring MVC)的默认逻辑导致,和Tomcat本身无关。
Spring处理重定向地址时,会自动识别指向当前应用的本地地址:当传入的callback地址host为localhost/127.0.0.1,且端口和内置Tomcat监听端口(本次场景为8080)一致时,会被判定为应用内部重定向路径,自动使用当前请求的Host头替换原有地址的host、端口部分,该逻辑原本是为了适配反向代理场景下的重定向地址正确性。
Windows环境无法复现的原因是不同系统的主机名、监听地址解析规则存在差异,导致Spring没有匹配到「当前应用内部地址」的判定条件,因此不会触发重写逻辑。
解决方案
- 方案1:直接手动构造响应头,绕过Spring的重定向处理逻辑(最稳妥)
@GetMapping("/foobar") public ResponseEntity<Void> handleFoobar(@RequestParam String callback) { // 必须先做callback合法性白名单校验,防止开放重定向漏洞 if (!isValidCallback(callback)) { return ResponseEntity.badRequest().build(); } // 拼接自定义参数 String finalLocation = callback + "?customParam=xxx"; return ResponseEntity.status(HttpStatus.SEE_OTHER) .header(HttpHeaders.LOCATION, finalLocation) .build(); }
- 方案2:调整RedirectView的配置
如果项目中使用RedirectView处理重定向,可单独关闭自动重写逻辑:
RedirectView redirectView = new RedirectView(callback); // 关闭上下文相对路径解析 redirectView.setContextRelative(false); // 禁用当前服务地址自动匹配 redirectView.setHosts(new String[0]);
也可全局配置关闭默认规则:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { RedirectViewResolver redirectResolver = new RedirectViewResolver(); redirectResolver.setRedirectContextRelative(false); registry.viewResolver(redirectResolver); } }
- 方案3:通过配置文件全局关闭上下文相对重定向规则
在application.yml中添加如下配置:
spring: mvc: redirect: context-relative: false
注意:无论使用哪种方案,都必须对传入的callback参数做白名校验,避免出现开放重定向安全漏洞
内容的提问来源于stack exchange,提问作者Chr3is
相关产品推荐
相关产品推荐

