ajax跨域解决
问题来源
最近项目里面遇到一个问题,项目是前后端分离的,前端使用vue,后端java,然后呢,因为分离嘛,所以很有可能不部署在同一个服务器上,也就是请求可能会存在跨域问题,然后呢,一开始的解决方案是使用nginx的反向代理,把api的请求转发到我们的后台,但是后来有发现了可以跨域的方法,因此记录下来
前端
前端想跨域很简单,比如你发送的请求,全局定一个域名就好了,然后发包的时候直接加上去,比如http://www.xxx.com,然后封装的ajax请求,将url前面加上我们的域名,就基本上没啥问题了,但是前端这么做,需要后台的配合,因为ajax是不支持跨域的(包括同IP地址的不同端口的跨域),只有当服务器方的response返回一个所谓的Access-Control-Allow-Origin
的header,这个header定义了是否支持跨域请求,所以后台这边做了一下处理。
后台
创建过滤器
public class FinHttpRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("Access-Control-Allow-Origin", "*");
httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
代码很简单,就是利用过滤器,然后每次请求都把response拿过来,把header加上我们的Access-Control-Allow-Origin
这个标记,*
就是允许所有请求。
然后还要添加一个Access-Control-Allow-Headers,这样子就能允许跨域的时候发过来POST这种请求了,如果不加这个,就会报错
添加过滤器
去我们的web.xml里面,将刚刚的FinHttpRequestFilter添加进去
<filter>
<filter-name>requestFilter</filter-name>
<filter-class>Interceptor.FinHttpRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
就是把所有的路径都经过这个过滤器
OPTION处理(最关键的)
前面的其实百度都能找到,但是发现一个问题就是,并不能用,依然是错误。后来我用postman的拦截器抓了包发现,发送的并不是我想要的POST请求,而是OPTION请求(OPT)
那么查询了一下
跨域的请求,浏览器会先向该地址发送一个option请求,来验证是否支持跨域,这个option必须返回200,这个跨域才会被执行
那么我们就明白了,浏览器跨域发送option请求,然后根据option请求中的header来确定是否支持跨域,并进行我们设定好的跨域方法
所以知道了这个,只需要加入对OPTION请求的处理方法就好,而且不需要有任何的操作,所以我选择了对所有OPTION进行拦截,只要返回了200的响应码,就能够跨域成功了
@Controller
@RequestMapping(value = "/", method = RequestMethod.OPTIONS)
public class CmnCtrl {
@RequestMapping(value = "", method = RequestMethod.OPTIONS)
@ResponseBody
public String option(){
return "";
}
}
创建一个控制器,对所有OPTION执行一个返回结果,那么不管返回了什么,浏览器能通过200的状态码获知,我们的服务器是支持跨域的,就足够了