Ajax 跨域解决——SpringBoot学习

Posted JRookie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax 跨域解决——SpringBoot学习相关的知识,希望对你有一定的参考价值。

什么是跨域

在目前的前后端分离开发模式下,前端使用 Ajax 访问后端提供的接口获取数据,产生报错。

跨域发生的原因

  1. 浏览器的限制

  2. 发生跨域访问

  3. 发送的是 XHR(XMLHttpRequst) 请求

三者同时发生,就会发生跨域问题

解决方式

因为是三者同时发生,才能发生跨域问题,因此针对三者,处理其中的一个即可。

首先是浏览器的限制,需要指定参数让浏览器不做校验,但方法不太合理,需要每个人都去做修改。其次是发送的请求不要是 XHR 类型的,解决方式是 JSONP 。最后是针对跨域,分为两点,一是让被调用方支持跨域,在响应头中添加参数,表示支持跨域访问,核心是支持跨域,二是让调用方在请求中使用代理,将从 A 域名发送到 B 的请求通过代理,让 B 认为是从本域名来的,核心是隐藏跨域。

具体解决方式

针对浏览器,通过命令行的方式启动,让其不要做跨域校验即可。

1eg:chrome --disable-web-security

针对 XHR 方式,本身浏览器发送的是 json 请求,通过 jsonp 的方式,将其变为 js 的方式,核心是通过动态添加 script 的方式来封装了请求,从而解决跨域问题。

使用这种方式需要修改服务端的代码,修改方式如下:

1@ControllerAdvicepublic class JsonpAdvice extends AbstractJsonpResponseBodyAdvice (   
2    public JsonpAdvice() {        
3        super("callback");
4   }
5}

前端通过制定 dataType 的方式来发送请求,如下所示

 1$.ajax({   
2    url:base+"/get1",  
3    dataType"jsonp",   
4    jsonp"callback2"
5    cache: true,  
6    type:"post",    
7    success:function(json){
8        result = json;
9    }
10})

但使用这种方式仍然是不好的方式,其有如下弊端

  1. 需要服务器端改变代码,如果涉及调用第三方接口,根本无法完成;

  2. 只支持 GET 请求,在真是的业务场景中十分受限;

  3. 因为改变了请求的类型,从 XHR 变为了 js 方式,因此 XHR 的很多优良特性无法使用。

因此,解决跨域问题最好的方式还是通过解决跨域访问来解决,使用服务器端支持跨域或调用端隐藏跨域来解决。

调用方解决跨域(支持跨域)的3种解决方式

  1. 服务器端实现

  2. nginx 配置

  3. Apache 配置

使用 Filter 来实现

通过过滤器在所有请求的 Response 中添加字段来支持跨域访问。

 1public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
2    HttpServletRequest req = (HttpServletRequest) request;
3    HttpServletResponse res = (HttpServletResponse) response;
4    String origin =req.getHeader("Origin");  
5    if (!StringUtils.isEmpty(origin)){ // 动态添加访问地址,使得所有的域名都可以跨域访问
6        res.addHeader("Access-Control-Allow-Origin",origin);
7    }
8    String headers = req.getHeader("Access-Control-Request-Headers");   
9    if (!StringUtils.isEmpty(headers)){ // 动态添加自定义访问头
10        res.addHeader("Access-Control-Allow-Headers",headers);
11    }
12    res.addHeader("Access-Control-Allow-Methods","*");
13    res.addHeader("Access-Control-Max-Age","3600");
14    res.addHeader("Access-Control-Allow-Credentials","true");
15    chain.doFilter(request,response);
16}
17
18@Bean
19FilterRegistrationBean registrationBean(){
20    FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();
21    filterRegistrationBean.addUrlPatterns("/*");
22    filterRegistrationBean.setFilter(new CrosFilter());
23    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
24    filterRegistrationBean.setName("Ajax"); 
25    return filterRegistrationBean;
26
27}

被调用方解决跨域(隐藏跨域)的解决方式

在 Spring 框架中的解决方式:在需要的类或方法上加上注解, @CrossOrigin

Nginx 配置
Apache 配置
Nginx 和 Apache 的解决方式因为涉及到其两个框架的方式,因为还没有深入了解过,所以在这没有叙述,以后深入学习过后,再详细编写。


以上是关于Ajax 跨域解决——SpringBoot学习的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot+Ajax跨域安全问题及解决方法

SpringBoot+Ajax跨域安全问题及解决方法

Springboot如何优雅的解决ajax+自定义headers的跨域请求[转]

Ajax跨域springboot+cloud 学习Docker

SpringBoot支持AJAX跨域请求

SpringBoot学习-SpringBoot添加支持CORS跨域访问