繁体   English   中英

HTTP Ajax 通过 HTTPS 页面请求

[英]HTTP Ajax Request via HTTPS Page

我在 HTTPS 连接上有一些页面的网站。 从这些 HTTPS 页中,我必须使用 HTTP Ajax 请求来检索一些错误,例如空白字段。 但是此错误消息不会出现。 是否有任何解决方案,或者我必须提出 AJAX 请求以在 HTTPS 连接上提交文件?

由于同源策略,这是不可能的。

您还需要将 Ajax 请求切换到 https。

没有任何服务器端解决方案,只有一种方法可以让安全页面从不安全的页面/请求中获取一些东西,这就是 postMessage 和弹出窗口

我说弹出是因为该网站不允许混合内容。 但是弹出窗口并没有真正混合。 它有自己的窗口,但仍然能够通过 postMessage 与 opener 通信。

因此,您可以使用window.open(...)打开一个新的 http 页面,并让该页面为您发出请求


当我写这篇文章的时候想到了XDomain ,但这是一种使用新的fetch api的现代方法,优点是大文件的流式传输,缺点是它不适用于所有浏览器

您将此代理脚本放在任何 http 页面上

onmessage = evt => {
  const port = evt.ports[0]

  fetch(...evt.data).then(res => {
    // the response is not clonable
    // so we make a new plain object
    const obj = {
      bodyUsed: false,
      headers: [...res.headers],
      ok: res.ok,
      redirected: res.redurected,
      status: res.status,
      statusText: res.statusText,
      type: res.type,
      url: res.url
    }

    port.postMessage(obj)

    // Pipe the request to the port (MessageChannel)
    const reader = res.body.getReader()
    const pump = () => reader.read()
    .then(({value, done}) => done 
      ? port.postMessage(done)
      : (port.postMessage(value), pump())
    )

    // start the pipe
    pump()
  })
}

然后你在你的 https 页面中打开一个弹出窗口(注意你只能在用户交互事件上这样做,否则它会被阻止)

window.popup = window.open(http://.../proxy.html)

创建您的效用函数

function xfetch(...args) {
  // tell the proxy to make the request
  const ms = new MessageChannel
  popup.postMessage(args, '*', [ms.port1])

  // Resolves when the headers comes
  return new Promise((rs, rj) => {

    // First message will resolve the Response Object
    ms.port2.onmessage = ({data}) => {
      const stream = new ReadableStream({
        start(controller) {

          // Change the onmessage to pipe the remaning request
          ms.port2.onmessage = evt => {
            if (evt.data === true) // Done?
              controller.close()
            else // enqueue the buffer to the stream
              controller.enqueue(evt.data)
          }
        }
      })

      // Construct a new response with the 
      // response headers and a stream
      rs(new Response(stream, data))
    }
  })
}

并像通常使用 fetch api 一样发出请求

xfetch('http://httpbin.org/get')
  .then(res => res.text())
  .then(console.log)

不过,这可以通过以下步骤完成:

  1. 向您的网站(同一域)发送 https ajax 请求

    jQuery.ajax({ 'url' : '//same_domain.com/ajax_receiver.php', 'type' : 'get', 'data' : {'foo' : 'bar'}, 'success' : function(response) { console.log('Successful request'); } }).fail(function(xhr, err) { console.error('Request error'); });
  2. 例如,通过 php 获取 ajax 请求,并通过 http 向任何所需的网站发出 CURL 获取请求。

     use linslin\\yii2\\curl; $curl = new curl\\Curl(); $curl->get('http://example.com');

在某些情况下,可以将没有响应的单向请求发送到 TCP 服务器,而无需 SSL 证书。 与 HTTP 服务器相反,TCP 服务器将捕获您的请求。 但是,将无法访问从浏览器发送的任何数据,因为浏览器不会在没有肯定证书检查的情况下发送任何数据。 在特殊情况下,即使没有任何数据的裸 TCP 信号也足以执行某些任务。 例如,局域网内的物联网设备启动与外部服务的连接。 链接

这是一种“唤醒”触发器,可在没有任何安全性的端口上工作。

如果需要响应,可以使用安全的公共 https 服务器来实现,该服务器可以使用 Websockets 等将所需数据发送回浏览器。

我创建了一个名为cors-bypass的模块,它允许您在不需要服务器的情况下执行此操作。 它使用postMessage发送跨域事件,用于提供模拟 HTTP API( fetchWebSocketXMLHTTPRequest等)。

它基本上与Endless答案相同,但无需更改代码即可使用它。

用法示例:

import { Client, WebSocket } from 'cors-bypass'

const client = new Client()

await client.openServerInNewTab({
  serverUrl: 'http://random-domain.com/server.html',
  adapterUrl: 'https://your-site.com/adapter.html'
})

const ws = new WebSocket('ws://echo.websocket.org')
ws.onopen = () => ws.send('hello')
ws.onmessage = ({ data }) => console.log('received', data)

在 server.js 中创建一个绕过 API。 这对我有用。

app.post('/by-pass-api',function(req, response){
  const url = req.body.url;
  console.log("calling url", url);
  request.get(
    url,
    (error, res, body) => {
      if (error) {
        console.error(error)
        return response.status(200).json({'content': "error"}) 
}
        return response.status(200).json(JSON.parse(body))
        },
      )
    })

并使用 axios 或 fetch 调用它,如下所示:

const options = {
     method: 'POST',
     headers: {'content-type': 'application/json'},
     url:`http://localhost:3000/by-pass-api`, // your environment 
     data: { url },  // your https request here
    };

从 javascript 我尝试了几种方法,但我不能。

您需要一个服务器端解决方案,例如在 c# 上,我确实创建了一个调用 http、反序列化对象的控制器,结果是当我从 javascript 调用时,我正在从我的https://发出请求到我的 htpps://domain。 请看我的 C# 代码:

[Authorize]
public class CurrencyServicesController : Controller
{
    HttpClient client;
    //GET: CurrencyServices/Consultar?url=valores?moedas=USD&alt=json
    public async Task<dynamic> Consultar(string url)
    {
        client = new HttpClient();
        client.BaseAddress = new Uri("http://api.promasters.net.br/cotacao/v1/");
        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
        System.Net.Http.HttpResponseMessage response = client.GetAsync(url).Result;

        var FromURL = response.Content.ReadAsStringAsync().Result;

        return JsonConvert.DeserializeObject(FromURL);
    }

让我向你展示我的客户端(Javascript)

<script async>
$(document).ready(function (data) {

    var TheUrl = '@Url.Action("Consultar", "CurrencyServices")?url=valores';
    $.getJSON(TheUrl)
        .done(function (data) {
            $('#DolarQuotation').html(
                '$ ' + data.valores.USD.valor.toFixed(2) + ','
            );
            $('#EuroQuotation').html(
                '€ ' + data.valores.EUR.valor.toFixed(2) + ','
            );

            $('#ARGPesoQuotation').html(
                'Ar$ ' + data.valores.ARS.valor.toFixed(2) + ''
            );

        });       

});

我希望这对你有帮助! 问候

这对我有用。 在 server.js 或 index.js 中绕过 API。 我正在使用 express.js 库。

import express from 'express';
import bodyParser from 'body-parser'; // custom_code
import axios from 'axios'; // custom-code
let app = express();
const jsonParser = bodyParser.json();

app.post('/by-pass-api', jsonParser, async (req, response) => {
  const { url } = req.body;
  const data = { data: req.body.data };
  const result = await axios.post(url, data);
  response.send({ success: true, result: result });
});
  


app.listen(3000, () => {
    console.log(`Server is running as on port 3000`);
  });

创建一个 function 以使用 axios 调用您的本地主机服务器(您的应用程序服务器)或像这样获取:

url: http://your-http-api-url :这是外部 http url。

axios.post("http://localhost:3000/by-pass-api", {
              headers: { "content-type": "application/json" },
              url: `http://your-http-api-url`,
              data: {...your_payload},
            })

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM