这里写目录标题
- 一、什么是跨域问题
- 二、浏览器的同源策略
- 三、SpringBoot项目中解决跨域问题的5种方式:使用CORS
- 1、自定 web filter 实现跨域(全局跨域)
- 2、重写 WebMvcConfigurer(全局跨域)
- 3、 CorsFilter(全局跨域)
- 4、使用@CrossOrigin注解 (局部跨域)
一、什么是跨域问题
跨域问题,也称为跨域资源共享(CORS,Cross-Origin Resource Sharing)问题,主要出现在Web开发中,尤其是当前端代码和后端代码分别部署在不同的域名下时。由于浏览器的同源策略限制,一个域的网页中通过JavaScript发起的跨域请求会被浏览器阻止,除非响应报文包含了正确的CORS相关头部信息。
跨域问题主要涉及到以下几个关键点:
-
同源与跨源:如果两个页面的协议、域名和端口都相同,则它们是同源的;否则,它们是跨源的。
-
浏览器限制:浏览器默认会阻止跨源请求,除非后端服务器明确允许这种请求。
-
CORS头部:为了允许跨源请求,后端服务器需要在响应中包含特定的CORS头部,如Access-Control-Allow-Origin。
-
预检请求:对于某些类型的跨域请求(如带有自定义头部的请求或PUT/DELETE等请求),浏览器会先发送一个OPTIONS请求进行预检,以检查服务器是否允许这种请求。
解决跨域问题的方法有多种,包括但不限于:
- 使用CORS:在后端服务器上配置CORS策略,允许特定的跨源请求。
- 使用代理服务器:在前端和后端之间设置一个代理服务器,前端请求发送到代理服务器,再由代理服务器转发到后端服务器。
- JSONP:一种古老的跨域技术,利用<script>标签没有跨域限制的特性来实现跨域请求。但JSONP只支持GET请求,且存在安全隐患,而且前后端都需要写相应的代码。
- 设置document.domain:对于主域名相同而子域名不同的情况,可以通过设置document.domain来实现跨域。
在实际开发中,应根据具体需求和场景选择合适的跨域解决方案。
二、浏览器的同源策略
同源策略是浏览器的一个安全功能,它阻止从一个源加载的文档或脚本与另一个源的资源进行交互。这是为了防止恶意文档读取或修改另一个源加载的资源。同源策略限制了不同源之间的DOM访问、AJAX请求以及Web存储访问等。当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。此外浏览器是否启用跨域保护机制是又后端的响应Response来决定的
三、SpringBoot项目中解决跨域问题的5种方式:使用CORS
1、自定 web filter 实现跨域(全局跨域)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class MyCorsFilter implements Filter {
private static Logger LOGGER = LoggerFactory.getLogger(MyCorsFilter.class);
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "*");
LOGGER.info("reponse cors: Access-Control-Allow-Origin={}" +
", Access-Control-Allow-Methods={}" +
", Access-Control-Allow-Credentials={}" +
", Access-Control-Allow-Headers={}",
response.getHeader("Access-Control-Allow-Origin"),
response.getHeader("Access-Control-Allow-Methods"),
response.getHeader("Access-Control-Allow-Credentials"),
response.getHeader("Access-Control-Allow-Headers"));
chain.doFilter(req, res);
}
}
2、重写 WebMvcConfigurer(全局跨域)
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("http://example.com") // 允许哪些源的请求
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的HTTP方法
.allowedHeaders("*") // 允许的头部
.allowCredentials(true) // 是否允许发送cookies
.maxAge(168000); // 预检请求的缓存时间(秒)
}
}
3、 CorsFilter(全局跨域)
CorsFilter 是 Java Spring 框架中用于处理跨域请求(CORS,Cross-Origin Resource Sharing)的过滤器。通过使用 CorsFilter,你可以配置你的 Spring 应用以允许跨域请求,从而避免浏览器因同源策略而阻止这些请求。下面是一个简单的 Spring Boot 应用中如何使用 CorsFilter 的例子:
- 添加依赖(如果你使用 Spring Boot,这个依赖可能已经包含在内):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 创建 CorsFilter:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("*")); // 允许所有源进行访问
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); // 允许的方法
config.setAllowCredentials(true); // 是否发送cookie
config.setMaxAge(168000); // 预检间隔时间
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 对所有路径应用 CORS 配置
return new CorsFilter(source);
}
}
在这个例子中,我们创建了一个 CorsFilter Bean,它允许来自任何源的请求,并允许 GET、POST、PUT 和 DELETE 方法。我们还设置了 AllowCredentials 为 true,这意味着浏览器可以发送带有凭据(如 cookies、HTTP 认证及客户端 SSL 证明等)的请求。最后,我们设置了 CORS 预检请求的缓存时间为 168000 秒(即 2 天)。
- 启动你的 Spring Boot 应用。现在,你的应用应该能够处理跨域请求了。请注意,出于安全考虑,你不应该在生产环境中将 AllowedOrigins 设置为 *,除非你完全信任所有可能的源。通常,你会将 AllowedOrigins 设置为一个特定的域名列表。
4、使用@CrossOrigin注解 (局部跨域)
@CrossOrigin 是 Spring Framework 提供的一个注解,用于解决跨域资源共享(CORS)问题。通过在类或者方法上使用 @CrossOrigin 注解,你可以轻松地为 Spring MVC 控制器开启 CORS 支持。这个注解允许你指定哪些域、HTTP 方法以及头部可以被允许进行跨域请求。
- 在控制器类上使用
可以直接在控制器类上使用 @CrossOrigin 注解,以允许整个控制器的所有方法都接受跨域请求:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com", methods = {RequestMethod.GET, RequestMethod.POST})
public class MyController {
// ... 控制器方法 ...
}
- 在单个方法上使用
可以将 @CrossOrigin 注解添加到特定的控制器方法上,以仅允许该方法的跨域请求:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/someMethod")
@CrossOrigin(origins = "http://example.com")
public String someMethod() {
// ... 方法实现 ...
return "Response";
}
}
使用 @CrossOrigin 注解时,你可以指定多个允许的源,方法,头部等。这提供了一种灵活的方式来控制哪些跨域请求应该被允许。需要注意的是,出于安全考虑,你应该仔细考虑允许哪些源进行跨域请求,并限制允许的 HTTP 方法和头部。
最后,确保你的 Spring Boot 应用已经包含了 Spring Web 的依赖,并且你的控制器类和方法已经正确地映射到了相应的 URL 路径。这样,当来自允许源的请求到达时,Spring MVC 就会自动处理 CORS 预检请求,并在响应中包含正确的 CORS 头部。