通过 HTTPS 页面的 HTTP Ajax 请求

IT技术 javascript ajax
2021-01-20 20:22:33

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

6个回答

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

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

甚至跨域资源共享的工作草案也让它变得不可能:w3.org/TR/cors/#user-agent-security
2021-03-14 20:22:33
谢谢大家的回答。我已根据同源政策更改了我的网站。
2021-03-15 20:22:33
@NickSotiros 实际上某人的 css 可以连接到输入并将在这些输入中输入的所有数据发送到坏服务器。
2021-03-30 20:22:33
@NickSotiros 为什么你不希望它安全?缺点为零,HTTPS 页面上的 HTTP 请求可能会被 MITM 攻击以注入恶意 JS。
2021-03-31 20:22:33
@ceejayoz 好吧,如果您下载一个 js 脚本并执行它,您可能会受到 MITM 的攻击。但是如果你只是想在你的 css 中使用别人的背景图片或者下载一个 youtube 视频,你就不能。为什么浏览器会假设通过 ajax 请求加载的内容将由 javascript 来执行?有一个站点prezi.com,它允许您使用从外部资源中提取的在线内容生成在线演示文稿,它们必须使用代理。
2021-03-31 20:22:33

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

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

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


当我写这篇文章时想到了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)
我终于以一种非常简单的方式做到了这一点: w = window.open("",'_blank', 'toolbar=no,titlebar=no,status=no,menubar=no,scrollbars=no,resizable=no,left= 12000,顶部=12000,宽度=10,高度=10,可见=无','');w.location.href = MyURI; setTimeout(function() { w.close(); }, 6000)
2021-03-14 20:22:33
为什么要打开一个新窗口?你不能把请求放在 iframe 中吗?
2021-03-25 20:22:33
@Chiwda 不,因为您将安全内容与不安全内容混合在一起,因此使用弹出窗口不会混合
2021-03-27 20:22:33
很好,创建了一个cors-bypass无缝执行此操作的module
2021-04-11 20:22:33

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

  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');
    
我只知道可能端点,如何将这种方法用于我的网站。我的网站是 https,API 是http://5ty.org:8080/api/card/post
2021-03-14 20:22:33
缺点是如果您的页面有很多并发请求,那么您的服务器可能会饱和。
2021-03-14 20:22:33
这个概念很完美(使用与我的设置/项目相关的代码)。我在我的服务器上创建了一个 php 文件,并在 HTTP Url 上做了一个 curl 请求。我从我的 HTTPS 网站调用了这个文件,并发送了 API 所需的变量,瞧!
2021-04-03 20:22:33

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

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

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

我创建了一个名为 的modulecors-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)