跨域

序:这篇随笔是看了“晓风轻老师的ajax跨域完全讲解”的视频之后的笔记。

一、产生跨域的条件
  (一)浏览器同源策略的限制
  (二)请求跨域(协议、域名、端口不同)
  (三)请求的类型是XMLHttpRequest
  同时符合上面三条,才会发生跨域问题。

二、解决思路
  (一)改浏览器设置,使浏览器支持
    在Chrome浏览器安装目录执行 chrome --disable-web-security --user-data-dir=g:\temp3
    我测试失败了,有兴趣的同学可以试试,教程链接

  (二)JSONP(请求类型从xhr变成script)
    1.前端JSONP

$.ajax({  
    url: '',  
    dataType: 'jsonp',  
    success: function(json) {  
        result = json;
        }
    });
JSONP-jQuery

    这是使用的是jQuery,虽然jQuery把JSONP看做是ajax,其实真的不是一回事,具体可参考《说说JSON和JSONP...

    2.后台同步支持

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        super("callback");
    }
}
JSONP-springboot

    因为教程是基于springboot,所以这是springboot上的一种方法,但是这种方式在spingboot2.0上已经无法使用了!!!

    虽然方法已经过时了,但总体的思路是不变的,就是在后端返回数据时,不直接返回JSON,而是返回的javascript代码。

    下面是我按照JSONP协议实现的代码

<script type="text/javascript">
var afterJsonp = function(data){
    alert('经过jsonp的data是:' + data.data);
};
var url = "http://127.0.0.1:8080/test/testJsonp?data=something&callback=afterJsonp";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
JSONP-前端
@GetMapping("/testJsonp")
public String testJsonp(String data,String callback) {
    //简单的处理下传参
    data += " after jsonp";
    String ret = callback + "({\"data\":\""+data+"\"})";
    return ret;
}
JSONP-后端

    JSONP的弊端:服务器需要改代码(加拦截器、加注解或者别的什么方式)、只支持GET、不是XHR

  (三)支持跨域(被调用方支持跨域/调用方隐藏跨域)
    1.被调用方解决-支持跨域
      (1)服务器实现-通过filter解决

@SpringBootApplication
public class AjaxserverApplication {

    public static void main(String[] args) {
        SpringApplication.run(AjaxserverApplication.class, args);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean registerFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.addUrlPatterns("/*");
        bean.setFilter(new CrosFilter());
        return bean;
    }

}
Filter添加
public class CrosFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "*");
        chain.doFilter(request, response);
    }

}
Filter实现

      (2)Nginx 这里直接放视频教程

      (3)Apache 这里直接放教程视频

      (4)如果是spring框架,只需要在类或方法上加注解“@CrossOrigin”

    2.调用方解决-隐藏跨域(通过方向代理实现)
      (1)Nginx 这里直接放视频教程

      (2)Apache 这里直接放视频教程

三、额外知识点
  (一)简单请求和非简单请求

同时满足下面两点就是简单请求
    1.请求方法是以下三种方法之一:HEAD、GET、POST
    2.HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

 

这里推荐下阮一峰老师的《跨域资源共享 CORS 详解》,对应的是上面的“服务器实现-通过filter解决”这种方式。

说点题外话,距离上篇随笔,已经过去了快两年,这两年的学习和工作就像随笔一样,停滞不前,有时候都有想放弃“写bug”的冲动。唉,不够努力,只会被时代抛弃...

 

posted @ 2019-08-18 22:20  鲜橙  阅读(189)  评论(0编辑  收藏  举报