2013-02-21 60 views
102

我试图使用AJAX加载跨域HTML页面,但除非数据类型是“jsonp”,否则我无法获得响应。然而,使用jsonp浏览器期待脚本MIME类型,但接收“文本/ HTML”。使用jQuery加载跨域端点AJAX

我的请求代码是:

$.ajax({ 
    type: "GET", 
    url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&[email protected]&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute", 
    dataType: "jsonp", 
}).success(function(data) { 
    $('div.ajax-field').html(data); 
}); 

是否有使用JSONP的请求,避免的方法吗?我已经尝试过使用crossDomain参数,但它不起作用。

如果不是有什么方法可以接收jsonp中的html内容吗?目前控制台在jsonp回复中说“意外的<”。

回答

191

jQuery的阿贾克斯注

  • 由于浏览器的安全限制,大多数阿贾克斯请求都受到了same origin policy;该请求无法成功从不同的域,子域,端口或协议中检索数据。
  • 脚本和JSONP请求不受相同的源策略限制。

有克服跨域屏障的一些方法:

有一些插件,与跨帮助 - 域个请求:

注意!

克服这个问题的最好办法,就是通过在后台建立自己的代理,让代理将指向其他领域的服务,因为在后端不存在相同的起源政策限制。但是如果你不能在后端做到这一点,那么请注意以下提示。


警告!

使用第三方代理不是一个安全的做法,因为他们可以跟踪你的数据,所以它可以用公共信息中使用,但从来没有私人数据。


下面使用所示的代码示例jQuery.get()jQuery.getJSON(),两者都是的jQuery.ajax()

速记方法


CORS Anywhere的

CORS Anywhere是一个node.js代理它将CORS头添加到代理请求。
要使用API​​,只需在URL前加上URL即可。 (支持HTTPS:看github repository

如果你想自动启用跨域请求需要的时候,可以使用下面的代码片段:

$.ajaxPrefilter(function (options) { 
    if (options.crossDomain && jQuery.support.cors) { 
    var http = (window.location.protocol === 'http:' ? 'http:' : 'https:'); 
    options.url = http + '//cors-anywhere.herokuapp.com/' + options.url; 
    //options.url = "http://cors.corsproxy.io/url=" + options.url; 
    } 
}); 

$.get(
    'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing', 
    function (response) { 
     console.log("> ", response); 
     $("#viewer").html(response); 
}); 


无论产地

Whatever Origin是一个跨域jsonp访问。这是anyorigin.com的开源替代品。

google.com,取数据,你可以使用这个片段:

// It is good specify the charset you expect. 
// You can use the charset you want instead of utf-8. 
// See details for scriptCharset and contentType options: 
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings 
$.ajaxSetup({ 
    scriptCharset: "utf-8", //or "ISO-8859-1" 
    contentType: "application/json; charset=utf-8" 
}); 

$.getJSON('http://whateverorigin.org/get?url=' + 
    encodeURIComponent('http://google.com') + '&callback=?', 
    function (data) { 
     console.log("> ", data); 

     //If the expected response is text/plain 
     $("#viewer").html(data.contents); 

     //If the expected response is JSON 
     //var response = $.parseJSON(data.contents); 
}); 


CORS代理

CORS代理是一个简单的的node.js代理为任何网站启用CORS请求。 它允许您网站上的JavaScript代码访问其他域上的资源,这些资源通常会因同源策略而被阻止。

它是如何工作的? CORS代理利用跨源资源共享,这是一项与HTML 5一起添加的功能。服务器可以指定他们希望浏览器允许其他网站请求他们托管的资源。 CORS Proxy只是一个HTTP代理服务器,它在响应中添加一个标题,标明“任何人都可以请求这个”。

这是实现此目标的另一种方式(请参见www.corsproxy.com)。所有你需要做的是剥离http://www。从URL被代理,并与www.corsproxy.com/

$.get(
    'http://www.corsproxy.com/' + 
    'en.wikipedia.org/wiki/Cross-origin_resource_sharing', 
    function (response) { 
     console.log("> ", response); 
     $("#viewer").html(response); 
}); 


CORS代理浏览器预先设置URL

最近我发现这一个,它涉及到各种安全导向的跨源远程共享工具。但它是一个以Flash作为后端的黑盒子。

你可以看到它在这里的行动:CORS proxy browser
获取GitHub上的源代码:koto/cors-proxy-browser

+4

您也可以从这里部署您自己的WhateverOrigin.org版本(或自行使用的代码):https://github.com/ripper234/Whatever-Origin/ – EpicVoyage 2013-11-17 14:18:33

+0

我已经试过这段代码,它工作正常从跨域加载HTML,但请求的HTML包含未加载响应的图像。意味着返回的跨域请求的HTML不包含图像。有没有什么办法来加载图像也????? – Hitesh 2014-01-21 11:39:10

+1

图像,CSS和外部JavaScript可以从另一个来源引用,因此,在响应中,您可以通过HTML字符串并替换外部资源的src – jherax 2014-01-21 17:00:19

9

如果外部站点不支持JSONP或CORS,则唯一的选择是使用代理。

在请求该内容的服务器上构建一个脚本,然后使用jQuery ajax命中服务器上的脚本。

19

您可以使用Ajax的跨域一个jQuery插件。 使用此插件,您可以使用jQuery.ajax()跨域。它使用谷歌的服务来实现这一目标:

的AJAX跨源插件使用谷歌Apps脚本作为代理JSON 吸气其中JSONP未实现。当您将crossOrigin 选项设置为true时,插件会将原始网址替换为Google地址,并将其作为编码的url参数发送。 Google脚本使用Google服务器资源获取远程数据,然后 将其作为JSONP返回给客户端。

这是非常简单易用:

$.ajax({ 
     crossOrigin: true, 
     url: url, 
     success: function(data) { 
      console.log(data); 
     } 
    }); 

你可以在这里阅读更多: http://www.ajax-cross-origin.com/

+12

就我而言,这个插件从来没有工作。它在Chrome上不会执行任何操作。 – Michael 2014-08-29 11:19:37

+0

如何验证服务器? – sttaq 2015-04-23 15:11:52

+2

放入'http:// google.com'将无法使用此解决方案。 – Adam 2016-01-05 06:40:25

-7

想通了。 改用此。

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle'); 
+0

你在那里使用的代码是无关紧要的。重要的是服务器端CORS头。 – Quentin 2015-06-16 12:49:02

0

我发布这个以防万一有人面临我现在面临的同样的问题。我有一台配有ZebraNet打印服务器的Zebra热敏打印机,它提供了一个基于HTML的用户界面,用于编辑多个设置,查看打印机的当前状态等。我需要获取打印机的状态在ZebraNet服务器提供的那些html页面之一中,例如,在浏览器中向用户发送alert()消息。这意味着我必须先使用Javascript获取该页面。尽管打印机位于用户PC的局域网内,但这个Same Origin Policy仍然在我的路上。我尝试过JSONP,但服务器返回HTML,但我还没有找到修改其功能的方法(如果可以的话,我已经设置了魔法标头Access-control-allow-origin:*)。所以我决定用C#编写一个小型控制台应用程序。它必须以管理员身份运行才能正常工作,否则它会投降:D是一个例外。以下是一些代码:

// Create a listener. 
     HttpListener listener = new HttpListener(); 
     // Add the prefixes. 
     //foreach (string s in prefixes) 
     //{ 
     // listener.Prefixes.Add(s); 
     //} 
     listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere, 
     //because the printer is accessible only within the LAN (no portforwarding) 
     listener.Start(); 
     Console.WriteLine("Listening..."); 
     // Note: The GetContext method blocks while waiting for a request. 
     HttpListenerContext context; 
     string urlForRequest = ""; 

     HttpWebRequest requestForPage = null; 
     HttpWebResponse responseForPage = null; 
     string responseForPageAsString = ""; 

     while (true) 
     { 
      context = listener.GetContext(); 
      HttpListenerRequest request = context.Request; 
      urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent 
      Console.WriteLine(urlForRequest); 

      //Request for the html page: 
      requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest); 
      responseForPage = (HttpWebResponse)requestForPage.GetResponse(); 
      responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd(); 

      // Obtain a response object. 
      HttpListenerResponse response = context.Response; 
      // Send back the response. 
      byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString); 
      // Get a response stream and write the response to it. 
      response.ContentLength64 = buffer.Length; 
      response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D 
      System.IO.Stream output = response.OutputStream; 
      output.Write(buffer, 0, buffer.Length); 
      // You must close the output stream. 
      output.Close(); 
      //listener.Stop(); 

所有用户需要做的就是以管理员身份运行该控制台应用程序。我知道这也太...令人沮丧和复杂,但是如果您无法以任何方式修改服务器,它就是域策略问题的解决方法。

编辑:从JS我做一个简单的Ajax调用:

$.ajax({ 
       type: 'POST', 
       url: 'http://LAN_IP:1234/http://google.com', 
       success: function (data) { 
        console.log("Success: " + data); 
       }, 
       error: function (e) { 
        alert("Error: " + e); 
        console.log("Error: " + e); 
       } 
      }); 

请求页面的HTML被返回并存储在数据变量。

-2

您需要CORS代理服务器代理您的请求从您的浏览器到适当的CORS headers请求的服务。这些服务的列表在下面的代码片段中。您也可以运行提供的代码片段查看您所在位置的此类服务。

$('li').each(function() { 
 
    var self = this; 
 
    ping($(this).text()).then(function(delta) { 
 
    console.log($(self).text(), delta, ' ms'); 
 
    }); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script> 
 
<ul> 
 
    <li>https://crossorigin.me/</li> 
 
    <li>https://cors-anywhere.herokuapp.com/</li> 
 
    <li>http://cors.io/</li> 
 
    <li>https://cors.5apps.com/?uri=</li> 
 
    <li>http://whateverorigin.org/get?url=</li> 
 
    <li>https://anyorigin.com/get?url=</li> 
 
    <li>http://corsproxy.nodester.com/?src=</li> 
 
    <li>https://jsonp.afeld.me/?url=</li> 
 
    <li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li> 
 
</ul>

+11

这不会以任何方式回答问题。 – 0xc0de 2016-09-06 07:05:57

+0

@ 0xc0de我终于写了答案。 – galeksandrp 2018-01-16 08:27:17

0

获取数据形成使用本地代理通过外部网站通过jherax你可以创建一个相应的外部URL获取的内容为你的PHP网页的建议,比发获取该页面的请求。

var req = new XMLHttpRequest(); 
req.open('GET', 'http://localhost/get_url_content.php',false); 
if(req.status == 200) { 
    alert(req.responseText); 
} 

为PHP代理,则可以使用https://github.com/cowboy/php-simple-proxy

0

只是把这个在你的PHP页面,它带病上班的头没有API:

header('Access-Control-Allow-Origin: *'); //allow everybody 

header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain 

$http_origin = $_SERVER['HTTP_ORIGIN']; //allow multiple domains 

$allowed_domains = array(
    'http://codesheet.org', 
    'http://stackoverflow.com' 
); 

if (in_array($http_origin, $allowed_domains)) 
{ 
    header("Access-Control-Allow-Origin: $http_origin"); 
}