使用带有 Jquery 跨域问题的 DHIS 2 API

Posted

技术标签:

【中文标题】使用带有 Jquery 跨域问题的 DHIS 2 API【英文标题】:Using DHIS 2 API With Jquery Cross domain issue 【发布时间】:2014-09-27 09:38:10 【问题描述】:

我正在尝试实现一个使用 DHIS 2 API 的 javascript 应用程序。我花了一整天的时间尝试使用 Jquery 进行身份验证。

API 说 (https://www.dhis2.org/doc/snapshot/en/user/html/ch32s02.html) 您需要使用 base 64 身份验证。我试图在 Jquery 中实现它,但我遇到了跨域问题。我曾尝试使用 DHIS 2 演示 (https://apps.dhis2.org/dev/) 进行身份验证,但未成功。然后我在本地计算机上设置了一个本地副本,但我仍然遇到与 DHIS 2 在不同端口上运行相同的问题。

我尝试过 jsonp 和 CROS,但没有成功。

这是我目前正在尝试的代码

$(function()
  var base_url = "http://apps.dhis2.org/demo/";
  var login = 'dhis-web-commons-security/login.action?authOnly=true';
  var current_user_url = 'api/users.json';
  var params = 
       'j_username':'admin',
      'j_password':'district'
 ;


 function base_64_auth(user,password)  
      var tok = user + ':' + password;
      var hash = Base64.encode(tok);
      return "Basic " + hash;
 

 var auth = base_64_auth('admin','district');

 $.ajax(
      url : base_url+login,
     data : params,
     type : 'POST',
     dataType : 'text',
     crossDomain : true,
     xhrFields : 
          'withCredentials':true
     ,
     beforeSend : function(req) 
          req.setRequestHeader('Authorization',auth);
     ,
     success : function(data)
          console.log('authentification succeded');
          alert('success');
          //userInfo();
     ,error : function(xhr,type,msg) 
          console.log(xhr.responseText);
          console.log(type);
          console.log(msg);
     
 );

);

我正在使用一个简单的库进行 base64 编码 www.webtoolkit.info/javascript-base64.html#.U9_O2XVdWkA

检查控制台我看到这个错误:

XMLHttpRequest 无法加载 http://apps.dhis2.org/demo/dhis-web-commons-security/login.action?authOnly=true。请求被重定向到'http://apps.dhis2.org/demo/dhis-web-commons/security/login.action?failed=true',这对于需要预检的跨域请求是不允许的。

如果有人曾经使用过 API,我会很感激他的帮助,或者如果你知道任何其他方式(包括其他语言)我可能能够与 API 交谈,我可能会去。

非常感谢。

【问题讨论】:

【参考方案1】:

跨域请求通常会被浏览器阻止。我自己在一个小组项目中使用 DHIS2 API,我们通过在 chrome 中禁用同源策略来解决这个问题,方法是运行:

google-chrome --disable-web-security

请注意,您仍然需要验证对演示服务器的请求,并且此解决方案无论如何都不理想。我猜最好的方法是在本地部署服务器并将所有文件放在服务器上,以便请求发生在与服务器相同的域上。另请注意,在 chrome 中禁用网络安全时,最好使用其他浏览器来处理邮件、facebook 等。

【讨论】:

【参考方案2】:

DHIS 2.18 版有一个启用 CORS 的选项。可以在系统设置 -> 远程访问

中列出应该允许 CORS 访问的域

https://www.dhis2.org/218

【讨论】:

【参考方案3】:

试试下面的php代码:

$post_string_b64 = base64_encode("user:password");

$auth = 'Authorization: Basic '.$post_string_b64;

$ch = curl_init("dhis2server/api/dataSets?paging=false");

curl_setopt($ch, CURLOPT_HTTPHEADER, array($auth));

curl_setopt($ch, CURLOPT_HEADER, 1);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);

$html = curl_exec($ch);

然后您会得到一个 json 响应,您可以通过以下方式使其可读:

$pattern = '/\(.+)\/';

preg_match($pattern, $html, $matches);

$json = json_decode($matches[0], true);

代码应该是不言自明的,但有什么不清楚的地方可以随时提问,

问候

【讨论】:

【参考方案4】:

在 2.18 版中,DHIS 2 增加了对 CORS 的支持,允许跨不同来源/域共享资源。

您可以设置一个域名白名单,您的 DHIS 2 实例将接受来自应用程序 > 设置 > 访问下的请求。换句话说,您必须在 DHIS 2 中定义您计划从中请求 DHIS 2 数据的域。因此,如果您计划在 webportal.org 上设置一个从 DHIS 2 检索数据的 Web 门户,那么您必须将 webportal.org 定义为列入白名单的 CORS 域。

Docs here

【讨论】:

【参考方案5】:

@Ajmal A 我可以确认在 系统设置 -> 访问 -> CORS 白名单 中编辑适当的 CORS 设置是有效的。我们使用的是 DHIS2 2.25 版。

我现在正在localhost:3000 上处理我们的客户端应用程序,在列入白名单后,我现在可以使用以下 jQuery AJAX 调用来获取数据。

var apiUrl = "https://<YOUR_URL>/api/<YOUR_RESOURCE>?format=json";
$.ajax(
    url: apiUrl,
    type: "GET",
    crossDomain: true,
    xhrFields : 
        'withCredentials':true
     ,
    dataType : "json",
    username: "<YOUR_USERNAME>",
    password: "<YOUR_PASSWORD>"
)
  .done(function( json ) 
      console.log(json);
  )
  .fail(function( xhr, status, errorThrown ) 
    console.log( "AJAX request failed on " + apiUrl );
    console.log( "Error: " + errorThrown );
    console.log( "Status: " + status );
    console.dir( xhr );
  )
  .always(function( xhr, status ) 
    console.log( "AJAX request closed." );
  );

【讨论】:

【参考方案6】:

您无法从外部 DHIS 平台(即不同的域)访问。 DHIS 不允许这样做。 我也花了两天时间。然后,DHIS 志愿者告诉了我。

【讨论】:

感谢您的回答。我最终使用 Java 而不是 Javascript 调用 API。现在可以正常使用了

以上是关于使用带有 Jquery 跨域问题的 DHIS 2 API的主要内容,如果未能解决你的问题,请参考以下文章

使用 API(带有两个 jQuery 版本和跨域的页面)

由于跨域请求,带有 Jquery 文件上传的 Carrierwave_Direct 不会重定向

带有 jquery.ajax() 的跨域“授权”标头

带有自定义标头的跨域 jquery ajax api 调用未命中服务器

jQuery 跨域 POST 恶作剧

Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例