Ajax 跨域解决——SpringBoot学习
Posted JRookie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax 跨域解决——SpringBoot学习相关的知识,希望对你有一定的参考价值。
什么是跨域
在目前的前后端分离开发模式下,前端使用 Ajax 访问后端提供的接口获取数据,产生报错。
跨域发生的原因
浏览器的限制
发生跨域访问
发送的是 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})
但使用这种方式仍然是不好的方式,其有如下弊端
需要服务器端改变代码,如果涉及调用第三方接口,根本无法完成;
只支持 GET 请求,在真是的业务场景中十分受限;
因为改变了请求的类型,从 XHR 变为了 js 方式,因此 XHR 的很多优良特性无法使用。
因此,解决跨域问题最好的方式还是通过解决跨域访问来解决,使用服务器端支持跨域或调用端隐藏跨域来解决。
调用方解决跨域(支持跨域)的3种解决方式
服务器端实现
nginx 配置
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+自定义headers的跨域请求[转]