浏览器跨域问题,教你手写实现jsonp跨域

跨域概述
为什么会有跨域
跨域解决办法:1、jsonp;2、后台代理
手写实现jsonp跨域(包括服务器端代码)

跨域问题

A服务器上的页面去获取B服务器上的资源,由于XMLHttpRequest同源策略限制,A页面是获取不到数据的。

同源:协议、域名、端口号任何一个都要相同,否则就会出现跨域请求。

为什么会跨域

为了安全

解决办法

方法一:jsonp

原理:使用script标签可以跨域请求资源的特性,去发送请求,得到数据

  • 核心思想
    动态在页面创建script标签,然后给src设置url,这个url就是跨域请求的链接,然后在页面声明一个方法,这个方法名要和后台返回的数据里带有的名字一样,一般情况下,这个名字是动态设置的,在url中传给后台。
  • 代码示例
  // localhost:9528 服务器 
  // index.html 
  
    
  
  
  // localhost:9527 服务器
  // json/getData 接口 (基于express框架)
  router.get("/getData", function (req, res) {
    res.send("getJson({a:1,b:2,c:3})")
  });
  • 效果图


    输出结果
  • 总结
    当script标签去加载 getData?call=getJson 接口时(就当是去请求一个js文件),接口返回数据后,浏览器会去执行得到的数据,这个时候浏览器发现数据是 getJson({a:1,b:2,c:3}) ,那这个getJSON是一个方法呀,所以他会立即执行这个方法,而这个上面我们已经定义好了,所以控制台就打印除了数据,如上图。

这只是一个简单的实现原理说明,现在有成熟的库可以使用 json ,如果有时间,后期将出关于jsonp框架源码分析的文章。

  • jsonp的缺点:只能解决文本类型的数据跨域,如果是图片呢?那就得需要下面这种方式了。
方法二:后台代理

原理:自己搭建一个服务器,提供一个接口,以供前端页面使用,前端页面把url链接发送给后台;然后接到参数后,服务器发送http请求(这儿可以设置各种请求头),接到数据然后返回给页面就行了。

  • 使用场景:在之前写的一个页面,图片路径是用的微信公众号发布的图片,但是在我的项目中请求这些图片,就会出现如下图一样的问题。


    微信公众号图片防盗链

    当然,除了本文要讲的方式之外,还有其他解决办法,比如 iframe 标签,但是图片过多的话,这个方式就不太好了(我的页面里面将全是iframe标签)。我的页面是运行在手机端的,所以还要考虑性能问题,只有把压力交给了服务器。这是效果图,里面图片全是公众号的图片。


    效果图
  • 代码示例
// 前端代码

//  前面 host/micro-site/change 自己服务器的域名和接口
//  url链接是图片的路径 
// 服务器接到url后,发送http请求,根据url请求数据,然后返回给前端页面。
// 后端代码 java
    @GetMapping("change")
    public void image(String url, HttpServletResponse response) {
        response.setHeader("Content-Type", "image/*");
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Referer", "");
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36");
        try {
            CloseableHttpResponse execute = httpClient.execute(httpGet);
            HttpEntity entity = execute.getEntity();
            entity.writeTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 后台代理缺点:这种方式显得有些笨重,多了一层数据请求,本来发送到一个服务器就可以了,现在要通过两台服务器才能返回数据,速度相对慢了一些。

你可能感兴趣的:(浏览器跨域问题,教你手写实现jsonp跨域)