Ajax 跨域解决——SpringBoot学习

Posted jrookie

tags:

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

·

什么是跨域

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

 

跨域发生的原因

1. 浏览器的限制

2. 发生跨域访问

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

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

 

解决方式

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

 

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

 

具体解决方式

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

1 eg:chrome --disable-web-security

 

 
技术分享图片

 

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

 

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

@ControllerAdvice

public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice (

    public JsonpAdvice() {

        super("callback");

    }

}

 

 

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

$.ajax({

    url:base+"/get1",

    dataType: "jsonp",

    jsonp: "callback",

    cache: true,

    type:"post",

    success:function(json){

        result = json;
    }
})

 

技术分享图片

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

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

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

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

 

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

技术分享图片技术分享图片?

 

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

1. 服务器端实现

2. nginx 配置

3. Apache 配置

 

使用 Filter 来实现

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

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

 

 
技术分享图片

 

 

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

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

 

Nginx 配置

Apache 配置

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

 

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

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

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

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

Ajax跨域springboot+cloud 学习Docker

SpringBoot支持AJAX跨域请求

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