前言
CORS(Cross-Origin Resource Sharing)"跨域资源共享",是一个W3C标准,它允许浏览器向跨域服务器发送Ajax请求,打破了Ajax只能访问本站内的资源限制,CORS在很多地方都有被使用,开放Ajax访问可被跨域访问的服务器大大减少了后台开发的工作,前后台工作也可以得到很好的明确以及分工,下面我们就看讲一下如何让你的SpringBoot项目支持CORS跨域。
一般来说,前后端分离的跨域问题最好是通过nginx配置反向代理来解决,nginx监听同样的IP和端口,然后通过URL前缀来区分是请求到前端还是后端,然后代理到前端或者后端,对于浏览器来说前后端都都是同源(IP和端口一样),就不存在跨域问题。
这里记录一下后端处理跨域,不同版本的springboot或者一些其他依赖会导致跨域失败,所以最好使用nginx。
注意:部分IE浏览器跨域功能默认是关闭的,需要打开:
工具--internet选项--安全--自定义级别--其它--通过域访问数据源
后端跨域配置主要有三种方式:
1.使用注解
2.实现WebMvcConfigurer接口
3.配置过滤器
方法一、使用注解(@CrossOrigin)
// 实现跨域注解
// origin="*"代表所有域名都可访问
@CrossOrigin(origins = "*")
@RestController
public class TestController {
@RequestMapping("getTestList")
public String getTestList(){
//此处省略相应代码
}
}
方法二、实现WebMvcConfigurer接口
package com.xx.xx;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Spring MVC 配置
*/
@Configuration
public class CopyOfWebMvcConfig implements WebMvcConfigurer {
//服务器支持跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST","OPTIONS","DELETE")
.allowedHeaders("*")
.exposedHeaders("Access-Control-Allow-Headers",
"Access-Control-Allow-Methods",
"Access-Control-Allow-Origin",
"Access-Control-Max-Age",
"X-Frame-Options")
.allowCredentials(false)
.maxAge(3600);
}
}
方法三、配置过滤器
第一步:写一个解决跨域问题的过滤器
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
/**
* 跨域请求配置
* @author zhh
* 2018-12-14
*/
public class CorsFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
/**
* 跨域请求配置说明:
* Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://aad.aa/bb/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略
Access-Control-Allow-Credentials: 是否允许请求带有验证信息,
Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在
Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数
Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开
Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
log.info("CorsFilter_方法执行");
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*"); // *表示允许所有
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); // *表示允许所有
res.setHeader("Access-Control-Max-Age", "0");
res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); // *表示允许所有
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("XDomainRequestAllowed","1");
chain.doFilter(request, response);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
第二步:把我们写过滤器注册到容器里面(springboot的方式)
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 过滤器配置(本地配置,部署到服务器的时候注释掉)
* @author zhh
* 2018-12-14
*/
@Configuration
public class WebFileterConfig {
/**
* 配置过滤器
* order属性:控制过滤器加载顺序:数字越小,加载越早
* @return
*/
@Bean
public FilterRegistrationBean corsFilterRegistration() {
//新建过滤器注册类
FilterRegistrationBean registration = new FilterRegistrationBean();
// 添加我们写好的过滤器
registration.setFilter( new CorsFilter());
// 设置过滤器的URL模式
registration.addUrlPatterns("/*");
registration.setOrder(Integer.MAX_VALUE-20); //order属性:控制过滤器加载顺序:数字越小,加载越早
return registration;
}
}
如果不是springboot,就需要在web.xml里面配置
<!-- ajax跨域请求过滤器配置 -->
<filter>
<filter-name>cors</filter-name>
<!-- 过滤器所在路径 -->
<filter-class>com.zhh.common.filter.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>