当您在DataV中使用API数据源时,可能会遇到跨域的问题。本文档为您介绍跨域问题的产生背景,并提供几种解决跨域问题的方法供您参考。

背景信息

用户A想创建一个可视化项目,用于向客户展示数据。当数据源类型选择API时,可能出现以下两种情况。
  • 若为远程服务器上的API,则可以勾选由服务器发起请求(HTTP代理)。勾选由服务器发起请求(HTTP代理)时,由DataV后台的服务器对API发起请求,超时时间为10秒,无法修改。
    服务器代理请求入口
  • 若为本地API,则不勾选由服务器发起请求(HTTP代理),且接口需要进行跨域数据配置。不勾选由服务器发起请求(HTTP代理)时,是由本地浏览器对该API进行访问,超时时间由浏览器来决定。

什么是跨域数据配置

用户A所包含的数据来自其自己的网站以及用户B的网站。自己网站上的数据可以通过类似http://userA.com/whoami这样的接口进行访问。用户B提供http://userB.com/isdad数据接口,但是当用户A发送一个Javascript ajax请求到用户B的网站上时,他将无法获得来自userB.com的数据。

打开浏览器,您可以看到如下标记为红色的文字 (Chrome)。
XMLHttpRequest 无法加载 http://userB.com/isdad。所请求的资源不带有“Access-Control-Allow-Origin”报头。因此不允许源站点“http://userA.com/whoami/”进行访问。

这意味着我们遇到了跨域问题。跨域问题产生的原因如下:

由于每个网站都包含各种用户接口、订单接口和文章接口,这意味着每个人都可以将这些接口返回的数据放入自己的网站,甚至是实时放入。因此浏览器采用同源策略,用于限制一个源站点的脚本获取其他源站点的资源。
说明 同源:如果两个页面的协议(HTTP)、端口(80) 和主机(userA.com)相同,那么这两个页面被认为是来自同一个源。

解决方案

  • A.x.com和B.x.com跨域

    如果两个网站的子域不同,仍然会存在跨域问题。例如http://56.alibaba.com/http://trade.alibaba.com/

    在页面中加入如下代码,将该页面声明为更高级别的域。
    <script>
      document.domain = "x.com";
    </script>
  • JSONP

    虽然JSONP是最经典、高效、浏览器兼容最好的解决方案,但由于它有非常高的跨站脚本攻击风险,所以DataV不支持这种方式。您可查阅相关资料了解具体信息。

  • 跨域资源共享
    说明 跨域资源共享:Cross Origin Resource Sharing,简称为CORS。已经与大多数较新的浏览器兼容。
    跨域资源共享的基本原理是在源站点B(本地API)中加入自定义的HTTP头部,使其他网站可以访问其资源。您可以根据实际情况,通过以下几种方式配置跨域资源共享。
    • 如果源站点B的接口数据需要被某一个网站使用,在数据服务器返回的报头信息中加入以下内容。
      Access-Control-Allow-Origin: http://userA.com
    • 如果源站点B的接口数据需要被多个网站使用,那么必须使用一个程序来动态生成报头信息。以下代码以PHP为例。
      <?php 
      if (is_my_bastard($_SERVER['HTTP_ORIGIN'])) {
      header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
      }
      ?>
    • 如果源站点B的接口数据需要被所用的网站使用,可以使用“*”
      Access-Control-Allow-Origin: *
    默认情况下CORS中不包含Cookie信息。如果您想添加Cookie,可执行以下步骤。
    1. 添加withCredentials参数。以JQuery为例,示例如下。
      $.ajax({
       url: "http://userB.com/isdad",
       xhrFields: {
         withCredentials: true
       }
      });
    2. 将服务器设置为允许使用报头凭证,但不允许使用通配符“*”。以PHP为例,示例如下。
      <?php 
      if (is_my_bastard($_SERVER['HTTP_ORIGIN'])) {
      header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); // Disallow “*”
      header("Access-Control-Allow-Credentials:true");
      }
      ?>

      更多详细信息请参见HTTP访问控制(CORS)