Spring Boot应用重定向至另一应用时如何添加自定义请求头?
解决Spring Boot重定向时添加自定义请求头的问题
你碰到的这个问题其实是HTTP协议的特性导致的——当你返回3xx重定向响应时,浏览器会发起一个新的独立请求到目标URI,这个新请求只会携带浏览器默认的请求头(比如你代码里拿到的User-Agent),而你在ResponseEntity里设置的test-header是返回给浏览器的响应头,根本不会被浏览器带到重定向的请求里。
下面给你几种可行的解决方案,根据你的实际业务场景选就行:
方案1:服务器端转发(优先推荐,若两个应用都由你管控)
既然两个都是你的Spring Boot应用,最靠谱的方式是让第一个应用直接作为客户端,向第二个应用发起HTTP请求,再把结果返回给用户——相当于服务器之间的内部调用,这样你可以自由设置任何请求头。
用RestTemplate实现(同步调用):
@Autowired private RestTemplate restTemplate; public @ResponseBody ResponseEntity<?> testMethod(@RequestHeader("User-Agent") String userAgent) { // 这里写你的请求验证逻辑... // 构建要发送给第二个应用的请求头 HttpHeaders targetHeaders = new HttpHeaders(); targetHeaders.set("test-header", "value"); targetHeaders.set("User-Agent", userAgent); // 也可以传递原请求的头信息 HttpEntity<Void> requestEntity = new HttpEntity<>(targetHeaders); // 调用第二个应用的接口 ResponseEntity<String> targetResponse = restTemplate.exchange( "http://localhost:8083/test1", HttpMethod.GET, // 根据目标接口的请求方法调整,比如POST requestEntity, String.class // 目标接口返回的数据类型,按需修改 ); // 把第二个应用的响应原封不动返回给客户端 return ResponseEntity.status(targetResponse.getStatusCode()) .headers(targetResponse.getHeaders()) .body(targetResponse.getBody()); }
用WebClient实现(Spring 5+推荐的异步调用):
@Autowired private WebClient webClient; public @ResponseBody Mono<ResponseEntity<?>> testMethod(@RequestHeader("User-Agent") String userAgent) { // 这里写你的请求验证逻辑... return webClient.get() .uri("http://localhost:8083/test1") .header("test-header", "value") .header("User-Agent", userAgent) .exchangeToMono(response -> { return response.toEntity(String.class) .map(entity -> ResponseEntity.status(response.statusCode()) .headers(entity.getHeaders()) .body(entity.getBody())); }); }
方案2:必须客户端重定向的场景(需要浏览器地址栏显示目标URI)
如果业务上必须让浏览器跳转到第二个应用的地址(地址栏要变),那只能通过间接方式传递信息:
方式A:URL参数传递(仅适合非敏感信息)
把需要的头信息作为URL参数拼到重定向URI里,第二个应用从请求参数中读取:
public @ResponseBody ResponseEntity<?> testMethod(@RequestHeader("User-Agent") String userAgent) { // 这里写你的请求验证逻辑... String targetUri = "http://localhost:8083/test1?test-header=value"; URI uri = URI.create(targetUri); return ResponseEntity.status(HttpStatus.FOUND) .location(uri) .build(); }
第二个应用的控制器接收参数:
@GetMapping("/test1") public ResponseEntity<?> test1(@RequestParam(value = "test-header", required = false) String testHeader) { // 使用testHeader做业务逻辑处理 return ResponseEntity.ok("Received header value: " + testHeader); }
方式B:Cookie传递
把需要的信息存在Cookie里,第二个应用从Cookie中读取(注意Cookie的域名和路径要匹配目标应用):
public @ResponseBody ResponseEntity<?> testMethod(@RequestHeader("User-Agent") String userAgent) { // 这里写你的请求验证逻辑... URI uri = URI.create("http://localhost:8083/test1"); HttpHeaders headers = new HttpHeaders(); headers.setLocation(uri); // 设置Cookie,Domain和Path根据实际情况调整 headers.add(HttpHeaders.SET_COOKIE, "test-header=value; Path=/; Domain=localhost"); return ResponseEntity.status(HttpStatus.FOUND) .headers(headers) .build(); }
第二个应用读取Cookie:
@GetMapping("/test1") public ResponseEntity<?> test1(@CookieValue(value = "test-header", required = false) String testHeader) { return ResponseEntity.ok("Received cookie value: " + testHeader); }
方式C:自动提交的HTML表单(适合POST场景)
返回一个包含自动提交表单的HTML页面,浏览器加载后会自动提交到目标地址,表单里可以携带需要的信息:
public @ResponseBody String testMethod(@RequestHeader("User-Agent") String userAgent) { // 这里写你的请求验证逻辑... return "<html><body>" + "<form id='redirectForm' method='POST' action='http://localhost:8083/test1'>" + "<input type='hidden' name='test-header' value='value'>" + "</form>" + "<script>document.getElementById('redirectForm').submit();</script>" + "</body></html>"; }
第二个应用从表单参数读取:
@PostMapping("/test1") public ResponseEntity<?> test1(@RequestParam("test-header") String testHeader) { return ResponseEntity.ok("Received form value: " + testHeader); }
注意:如果是敏感信息,不要用URL参数或表单传递(容易被拦截或泄露),优先选择服务器端转发或者加密后的Cookie。
内容的提问来源于stack exchange,提问作者vaibhav srivastava
相关产品推荐
相关产品推荐

