Springboot如何实现跨域?
文章目录
- 什么是跨域问题?
- 实现方式
- 实现 HandlerInterceptor
- 重写 WebMvcConfigurer(全局跨域)
- 使用@CrossOrigin注解 (局部跨域)
- 使用自定义filter实现跨域
- 在响应头中添加 Access-Control-Allow-Origin 等字段,如果希望允许所有域名访问 API,可以将值设置为 *:
- 使用 Nginx 配置
- 配置 Gateway 的路由
什么是跨域问题?
当域名,端口,协议三者存在任意一项不同时就需要解决跨域问题
实现方式
实现 HandlerInterceptor
创建一个类实现 HandlerInterceptor 接口,并在 preHandle 方法中设置响应头以实现跨域。
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")// 拦截所有的请求.allowedOrigins("*")// 可跨域的域名,*为所有.allowCredentials(true).allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")// 允许跨域的方法,可以单独配置.maxAge(3600);}
}
重写 WebMvcConfigurer(全局跨域)
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")// 拦截所有的请求.allowedOrigins("*")// 可跨域的域名,*为所有.allowCredentials(true).allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")// 允许跨域的方法,可以单独配置.maxAge(3600);}
}
使用@CrossOrigin注解 (局部跨域)
使用自定义filter实现跨域
创建一个类实现 javax.servlet.Filter 接口,并在 doFilter 方法中设置响应头以实现跨域。
@WebFilter
public class CorsFilter implements Filter {@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) res;response.setHeader("Access-Control-Allow-Origin", "http://example.com");response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");response.setHeader("Access-Control-Allow-Credentials", "true");chain.doFilter(req, res);}// ...
}
注意:使用 Filter 实现跨域时,Filter 会拦截所有请求,而不仅仅是跨域请求。因此,在设置响应头时需要谨慎,避免影响其他请求的正常处理。如果需要更细粒度的控制,可以考虑使用 @CrossOrigin 注解或拦截器来实现。
在响应头中添加 Access-Control-Allow-Origin 等字段,如果希望允许所有域名访问 API,可以将值设置为 *:
response.setHeader("Access-Control-Allow-Origin", "http://example.com")
使用 Nginx 配置
location / {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers X-Requested-With;add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;if ($request_method = 'OPTIONS') {return 204;}
}
配置 Gateway 的路由
- id: my_routeuri: http://localhost:8080predicates:- Path=/api/**filters:- RewritePath=/api/(?<segment>.*), /$\{segment}- AddResponseHeader=Access-Control-Allow-Origin:http://example.com- AddResponseHeader=Access-Control-Allow-Methods:GET, POST, PUT, DELETE- AddResponseHeader=Access-Control-Allow-Headers:Content-Type, Authorization- AddResponseHeader=Access-Control-Allow-Credentials:true
这将允许来自 http://example.com 的跨域请求访问 Gateway 中的 API。