Ajax 跨域解决(一)——SpringBoot学习

什么是跨域

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

 

跨域发生的原因

1. 浏览器的限制

2. 发生跨域访问

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

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

 

解决方式

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

 

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

 

具体解决方式

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

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: "callback2",

    cache: true,

    type:"post",

    success:function(json){

        result = json;
    }
})

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

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

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

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

 

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

 

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

1. 服务器端实现

2. Nginx 配置

3. Apache 配置

 

使用 Filter 来实现

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

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;

    HttpServletResponse res = (HttpServletResponse) response;

    String origin =req.getHeader("Origin");

    if (!StringUtils.isEmpty(origin)){ // 动态添加访问地址,使得所有的域名都可以跨域访问

        res.addHeader("Access-Control-Allow-Origin",origin);

    }

    String headers = req.getHeader("Access-Control-Request-Headers");

    if (!StringUtils.isEmpty(headers)){ // 动态添加自定义访问头

        res.addHeader("Access-Control-Allow-Headers",headers);

    }

    res.addHeader("Access-Control-Allow-Methods","*");

    res.addHeader("Access-Control-Max-Age","3600");

    res.addHeader("Access-Control-Allow-Credentials","true");

    chain.doFilter(request,response);

}



@Bean

FilterRegistrationBean registrationBean(){

    FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean();

    filterRegistrationBean.addUrlPatterns("/*");

    filterRegistrationBean.setFilter(new CrosFilter());

    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);

    filterRegistrationBean.setName("Ajax");

    return filterRegistrationBean;

}

 

 

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

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

 

Nginx 配置

Apache 配置

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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值