Spring Boot 2.7.10中@CrossOrigin未限制非指定源请求问题排查
问题:@CrossOrigin注解未限制非指定源的后端调用请求
我基于JDK 8与Spring Boot 2.7.10实现了两个Spring Boot应用,其中一个应用通过REST调用请求另一个应用。在被调用的应用中,我使用@CrossOrigin注解配置了CORS,指定允许的源为localhost:8085。
我将调用方应用部署在8080以外的其他端口,再次调用该带有@CrossOrigin注解的资源,理论上该资源应仅接受指定源的请求,但实际它也接受了其他源的请求。请问我是否遗漏了什么配置?@CrossOrigin并未限制不在源列表中的其他源发起的请求。
客户端代码
package com.example.CORSExampleClient.CORSClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class CORSClient { @Autowired private RestTemplate restTemplate; @GetMapping("callClient") public void callClient() { String response=restTemplate.getForObject("http://localhost:9000/getOrigin",String.class); System.out.println("Response "+response); } }
带CORS限制的被调用方资源代码
package com.example.CORSExample; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @CrossOrigin(origins = "http://localhost:8085") @RestController public class CORSController { @GetMapping("getOrigin") public String getOrigin(@RequestParam(required = false, defaultValue = "World") String name){ return "Hello "+name; } }
被调用方主类代码
package com.example.CORSExample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class CorsExampleApplication { public static void main(String[] args) { SpringApplication.run(CorsExampleApplication.class, args); } }
解答
这不是配置遗漏,而是对@CrossOrigin的作用范围理解有误:
@CrossOrigin是用来限制浏览器端发起的跨域请求的,它是浏览器同源策略安全机制的一部分,只有请求来自浏览器时,浏览器才会检查CORS响应头并拦截不符合规则的请求。- 你用
RestTemplate做的是后端服务之间的直接调用,这类请求不会经过浏览器,因此不会触发CORS检查,@CrossOrigin的配置对这类请求完全不起作用。
如果要限制后端服务之间的调用,需要用其他方式:
- 借助Spring Security添加请求鉴权,比如基于API密钥、OAuth2等方式验证调用方身份。
- 自定义拦截器或过滤器,检查请求头中的
Origin字段(若调用方会携带),或检查请求来源IP、自定义请求头,不符合规则则直接拒绝请求。
以下是自定义过滤器的示例:
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class OriginFilter implements Filter { private static final String ALLOWED_ORIGIN = "http://localhost:8085"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String origin = req.getHeader("Origin"); if (origin != null && !origin.equals(ALLOWED_ORIGIN)) { res.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } chain.doFilter(request, response); } }
在配置类中注册该过滤器:
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<OriginFilter> originFilter() { FilterRegistrationBean<OriginFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new OriginFilter()); registrationBean.addUrlPatterns("/getOrigin"); // 指定要拦截的接口 return registrationBean; } }
通过这种方式,就能限制只有指定源的请求(包括后端调用和浏览器请求)才能访问目标接口。
内容的提问来源于stack exchange,提问作者Darshana
相关产品推荐
相关产品推荐

