引言
现在许多web项目基本上都用前后端分离项目,那在实际开发过程当中碰到比较频繁的问题就是跨域问题了,导致前端无法请求到后端数据。
一、什么是跨域(CORS全称Cross-Origin Resource Sharing)
当浏览器地址的协议、域名、端口号与后端服务器地址中的任意一环不对等的话,即为跨域。接下来,我举几个案例会更加直观一点:
正确案例:
浏览器地址:http://127.0.0.1:8080/project/index.html
请求地址:http://127.0.0.1:8080/showIndex
跨域案例1(原因:协议不一致):
浏览器地址:http://127.0.0.1:8080/project/index.html
请求地址:https://127.0.0.1:8080/showIndex
跨域案例2(原因:主机不一致):
浏览器地址:http://127.0.0.1:8080/project/index.html
请求地址:http://127.0.0.2:8080/showIndex
跨域案例3(原因:端口不一致):
浏览器地址:http://127.0.0.1:8080/project/index.html
请求地址:http://127.0.0.1:8081/showIndex
备注:如果两个域名,它们所映射的ip地址是同一个,但是端口不一致,也会跨域
二、为什么会产生跨域
跨域的根本原因还是由于浏览器的同源策略的限制,也就是上述所说的必须要满足协议、主机、端口三个都要相等。
- 同源策略是浏览器最基本也是最核心的安全功能
- Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
- 同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互
三、解决方法
1、添加@CrossOrigin注解(局部)
备注:以下两种方式只针对单个类或者单个方法,适用于局部处理跨域
@CrossOrigin(origins = "*", maxAge = 3600)
@Controller
@RequestMapping(value = "/testCors")
public class TestCorsController {
}
@Controller
@RequestMapping(value = "/testCors")
public class TestCorsController {
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping(value = "/test")
@ResponseBody
public Object test() throws Exception{
Map<String,Object> map = new HashMap<String,Object>();
return map;
}
}
2、添加CorsFilter配置(全局)
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addExposedHeader("*");
corsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
return new CorsFilter(corsConfigurationSource);
}
}
3、重写WebMvcConfigure(全局)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOrigins("*")
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
4、手动写个filter设置响应头(全局)
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)servletRequest;
HttpServletResponse res=(HttpServletResponse)servletResponse;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
filterChain.doFilter(req, res);
}
@Override
public void destroy() {
}
}
<!--web.xml配置过滤器-->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>类的位置</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>
四、总结
以上就是跨域的简单介绍以及Spring比较常见的一些处理方式,适用于SpringBoot以及SSM框架,如果上诉讲解有问题都可以指出来哦,欢迎大家评论~
|