使用AJAX加载跨域端点


131

我正在尝试使用AJAX加载跨域HTML页面,但除非dataType为“ jsonp”,否则无法获得响应。但是,使用jsonp时,浏览器期望使用脚本mime类型,但接收到“ text / html”。

我的请求代码是:

$.ajax({
    type: "GET",
    url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_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回复中说“意外<”。


我已经通过创建proxy.php来解决此问题,如此处scode7.blogspot.com/2019/11/…所述
CodeDezk

Answers:


235

jQuery Ajax笔记

  • 由于浏览器安全性的限制,大多数Ajax请求都遵循相同的原始策略;该请求无法成功从其他域,子域,端口或协议检索数据。
  • 脚本和JSONP请求不受相同的原始策略限制。

有一些方法可以克服跨域障碍:

有一些插件可帮助处理跨域请求:

小心!

克服此问题的最佳方法是,在后端创建自己的代理,以便您的代理指向其他域中的服务,因为在后端不存在相同的原始策略限制。但是,如果您不能在后端执行此操作,请注意以下提示。


警告!

使用第三方代理不是安全的做法,因为它们可以跟踪您的数据,因此可以与公共信息一起使用,但绝不能与私人数据一起使用。


下面显示的代码示例使用jQuery.get()jQuery.getJSON(),它们都是jQuery.ajax()的简写方法。


任何地方的CORS

CORS Anywhere是一个node.js代理,它将CORS标头添加到代理请求中。
要使用API​​,只需在URL前面加上API URL。(支持https:见github仓库

如果要在需要时自动启用跨域请求,请使用以下代码段:

$.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);
});


无论起源

无论起源如何,都是跨域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 Proxy是一个简单的node.js代理,可为任何网站启用CORS请求。它允许您站点上的javascript代码访问其他域上的资源,这些资源通常由于同源策略而被阻止。

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

这是实现目标的另一种方法(请参阅www.corsproxy.com)。您所要做的就是删除http://www。从要代理的URL中添加,并在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代理浏览器

最近,我发现了这个,它涉及各种面向安全性的跨源远程共享实用程序。但这是一个以Flash为后端的黑盒子。

您可以在此处查看其运行情况:CORS代理浏览器
在GitHub上获取源代码:koto / cors-proxy-browser


4
您还可以从以下位置部署自己的WhateverOrigin.org版本(或移植代码供自己使用):github.com/ripper234/Whatever-Origin
EpicVoyage 2013年

1
图片,CSS和外部javascript可以从另一个来源引用,因此,在响应中,您可以遍历HTML字符串并替换外部资源的src
jherax 2014年

1
您好jherax我用whatorigin来获取一个html页面(只有这样对我有用,使用了yql,google等),但是非英文字符很奇怪。尝试对data.contents进行编码,但没有帮助
user217648 2014年

1
您好@Miru,正如标题所述:“使用jQuery AJAX加载跨域html页面”,我通过提供一些使用代理执行跨域请求的示例来回答标题。另外,为了回答问题的措辞,我提供了一些链接,以使用带有YQL的JSONP进行跨域请求。我邀请您阅读链接,它们非常有用。
jherax

1
最终与一起使用CORS Anywhere方法,$.ajaxPrefilter效果很好。非常感谢!
约书亚·品特

24

您可以使用Ajax跨源jQuery插件。使用此插件,您可以使用jQuery.ajax()跨域。它使用Google服务来实现此目的:

AJAX Cross Origin插件使用Google Apps脚本作为未实现jSONP的代理jSON getter。当您将crossOrigin选项设置为true时,插件将原始网址替换为Google Apps脚本地址,并将其作为已编码的网址参数发送。Google Apps脚本使用Google服务器资源来获取远程数据,并将其作为JSONP返回给客户端。

使用非常简单:

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

您可以在此处了解更多信息:http : //www.ajax-cross-origin.com/


21
就我而言,该插件从未使用过。它不会在Chrome上执行任何操作。
2014年

如何认证服务器?
sttaq 2015年

很棒!我正在使用的API不支持JSONP或CORS,因此这是唯一有效的方法。非常感谢!
JP Lew

jQuery的crossOrigin选项当然不会减轻同源策略。如果可以的话,我会删除此答案
Phil

13

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

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


5

只需将其放在您的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");
}

我想知道从哪里来$_SERVER['HTTP_ORIGIN']。我在PHP文档或其他任何地方都找不到它。
Zsolti

嗯,似乎只用AJAX请求填充了它。无论如何,谢谢您的回答。
Zsolti

0

如果有人遇到我现在面临的相同问题,我将发布此消息。我有一台配备ZebraNet打印服务器的Zebra热敏打印机,该服务器提供基于HTML的用户界面,用于编辑多个设置,查看打印机的当前状态等。我需要获取打印机的状态,该状态会显示在ZebraNet服务器提供的html页面之一中,例如,alert()向浏览器中的用户发送一条消息。这意味着我必须先在Javascript中获取该html页面。尽管打印机位于用户PC的LAN内,但该相同来源策略仍然坚定地坚持我的方式。我尝试了JSONP,但是服务器返回了html,但是我还没有找到修改其功能的方法(如果可以的话,我已经设置了魔术头Access-control-allow-origin:*)。因此,我决定用C#编写一个小型控制台应用程序。它必须以Admin身份运行才能正常工作,否则它将抛出: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并将其存储在data变量中。


0

要按照jherax的建议通过使用本地代理进行传递来获取外部网站的数据,您可以创建一个php页面,该页面从相应的外部url获取内容,然后将get请求发送到该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

您的URL这几天不工作,但是可以使用以下可行的解决方案来更新您的代码:

var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";

url = 'https://google.com'; // TEST URL

$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
    $('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


-2

您需要使用适当的CORS标头将来自浏览器的请求代理到请求的服务的CORS代理。此类服务的列表在下面的代码段中。您还可以运行提供的代码段,以从您所在的位置查看对此类服务的ping操作。

$('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

@ 0xc0de我终于写了答案。
galeksandrp

-7

弄清楚了。改用这个。

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

您在此处使用的代码无关紧要。重要的是服务器端的CORS标头。
昆汀2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.