使用 AJAX 加载跨域端点

IT技术 javascript jquery ajax cross-domain
2021-01-23 22:50:09

我正在尝试使用 AJAX 加载跨域 HTML 页面,但除非数据类型为“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 回复中说“意外 <”。

6个回答

jQuery Ajax 注释

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

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

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

当心!

解决这个问题的最好方法是在后端创建自己的代理,这样您的代理将指向其他域中的服务,因为在后端不存在同源策略限制。但是如果你在后端不能做到这一点,那么请注意以下提示。


**警告!**

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


下面显示的代码示例使用jQuery.get()jQuery.getJSON(),两者都是jQuery.ajax() 的速记方法


任何地方的 CORS

2021 更新

公共演示服务器 (cors-anywhere.herokuapp.com) 将在 2021 年 1 月 31 日之前非常有限

CORS Anywhere (cors-anywhere.herokuapp.com) 的演示服务器旨在作为该项目的演示。但是滥用已经变得如此普遍,以至于托管演示的平台 (Heroku) 要求我关闭服务器,尽管努力打击滥用。由于滥用及其流行,停机时间变得越来越频繁。

为了解决这个问题,我将进行以下更改:

  1. 速率限制将从每小时 200 次降至每小时 50 次。
  2. 到 2021 年 1 月 31 日,cors-anywhere.herokuapp.com 将停止作为开放代理服务。
  3. 从 2 月 1 日起。2021 年,cors-anywhere.herokuapp.com 将仅在访问者完成挑战后才提供请求:用户(开发者)必须访问 cors-anywhere.herokuapp.com 上的页面以临时解锁其浏览器的演示。这允许开发人员试用该功能,以帮助决定自托管或寻找替代方案。

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

无论起源

无论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 代理只是一个 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

你好@Miru,正如标题所说:“使用 jQuery AJAX 加载跨域 html 页面”,我通过提供一些使用代理执行跨域请求的示例来回答标题。另外,针对问题的措辞,我提供了一些链接,以使用 JSONP 和 YQL 进行跨域请求。我邀请您阅读链接,它们非常有用。
2021-03-12 22:50:09
最终使用了 CORS Anywhere 方法,$.ajaxPrefilter并且效果很好。非常感谢!
2021-03-17 22:50:09
嗨,jherax,我使用了whateverorigin 来获取一个 html 页面(只对我有用,使用了 yql、google 等)但非英文字符很奇怪。试图编码 data.contents 但没有帮助
2021-03-27 22:50:09
您还可以从这里部署您自己版本的 WhateverOrigin.org(或移植代码供您自己使用):github.com/ripper234/Whatever-Origin
2021-03-31 22:50:09
图像、CSS 和外部 javascript 可以从另一个来源引用,因此,在响应中,您可以遍历 HTML 字符串并替换外部资源的 src
2021-04-02 22:50:09

您可以使用 Ajax-cross-origin 一个 jQuery 插件。使用此插件,您可以使用jQuery.ajax()跨域。它使用 Google 服务来实现这一点:

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

使用起来非常简单:

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

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

就我而言,这个插件从来没有工作过。它在 Chrome 上没有任何作用。
2021-03-13 22:50:09
效果很好!我使用的 API 既不支持 JSONP 也不支持 CORS,所以这是唯一有效的方法。非常感谢!
2021-03-19 22:50:09
如何向服务器进行身份验证?
2021-03-24 22:50:09
jQuery 的crossOrigin选项当然不会减轻同源策略。如果可以,我会删除这个答案
2021-03-24 22:50:09

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

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

只要把它放在你的 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");
}
嗯,它似乎只填充了 AJAX 请求。无论如何,谢谢你的回答。
2021-03-12 22:50:09
我想知道从哪里来$_SERVER['HTTP_ORIGIN']我在 PHP 文档或其他任何地方都找不到它。
2021-03-24 22:50:09

我发布这个以防有人面临我现在面临的同样问题。我有一台 Zebra 热敏打印机,配备了 ZebraNet 打印服务器,它提供了一个基于 HTML 的用户界面,用于编辑多个设置、查看打印机的当前状态等。我需要获取打印机的状态,显示在由 ZebraNet 服务器提供的这些 html 页面之一中,例如,alert() 向浏览器中的用户发送消息。这意味着我必须首先在 Javascript 中获取该 html 页面。虽然打印机在用户 PC 的局域网内,但同源策略仍然坚定地挡在我的路上。我尝试了 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 被返回并存储在data变量中。