HTTP-запрос Ajax через страницу HTTPS

У меня есть сайт с некоторыми страницами по соединению HTTPS. На этих страницах HTTPS я должен использовать HTTP-запрос Ajax для поиска некоторых ошибок, таких как пустые поля. Но это сообщения об ошибках не приходят. Есть ли какое-либо решение, или я должен сделать этот запрос AJAX для файла по соединению HTTPS?

8 ответов

Решение

Это невозможно из-за одинаковой политики происхождения.

Вам также нужно будет переключить запросы Ajax на https.

Без какого-либо решения на стороне сервера, Theres - это только один способ, которым защищенная страница может получить что-то от небезопасной страницы / запроса, и это считается postMessage и всплывающее окно

Я сказал, что всплывающее окно не позволяет смешивать контент. Но всплывающее окно на самом деле не смешивается. У него есть собственное окно, но он все еще может общаться с открывателем с помощью postMessage.

Таким образом, вы можете открыть новую страницу http с window.open(...) и это делает запрос для вас (то есть, если сайт также использует CORS)


XDomain пришёл в голову, когда я написал это, но здесь есть современный подход, использующий новый API fetch, преимущество заключается в потоковой передаче больших файлов, недостатком является то, что он не будет работать во всех браузерах.

Вы помещаете этот прокси-скрипт на любую страницу 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))
    }
  })
}

И сделайте запрос, как вы обычно делаете с 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. получить ajax-запрос, например, по php, и сделать CURL-запрос на получение любого желаемого веб-сайта по http.

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

В некоторых случаях односторонний запрос без ответа может быть отправлен на сервер TCP без сертификата SSL. TCP-сервер, в отличие от HTTP-сервера, перехватит ваш запрос. Однако не будет никакого доступа к любым данным, отправленным из браузера, потому что браузер не будет отправлять данные без проверки положительного сертификата. А в особых случаях даже голого TCP-сигнала без каких-либо данных достаточно для выполнения некоторых задач. Например, для устройства IoT в локальной сети, чтобы начать подключение к внешней службе. Ссылка на сайт

Это своего рода триггер Wake Up, который работает на порте без какой-либо защиты.

В случае, если требуется ответ, это может быть реализовано с использованием защищенного публичного https-сервера, который может отправлять необходимые данные обратно в браузер, используя, например, веб-сокеты.

Сделайте обходной API в server.js. У меня это работает.

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

Я создал модуль под названием cors-bypass, что позволяет вам делать это без необходимости сервера. Оно использует postMessage отправлять междоменные события, которые используются для предоставления фиктивных HTTP API (fetch, WebSocket, XMLHTTPRequest так далее.).

Он в основном делает то же самое, что и ответ 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)

Это работает для меня. Сделайте обходной API в server.js или index.js. Я использую библиотеку 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`);
  });

Создайте функцию для вызова вашего локального сервера (вашего сервера приложений) с помощью axios или выборки следующим образом:

URL:http://your-http-api-url: это внешний http-адрес.

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

Из javascript я пробовал несколькими способами и не смог.

Вам нужно решение на стороне сервера, например, на C# Я создал контроллер, который вызывает http, en десериализует объект, и в результате я при вызове из javascript выполняю запрос из моего https: // домен в мой htpps:// домен. Пожалуйста, смотрите мой код 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) + ''
            );

        });       

});

Я желаю, чтобы это помогло вам! Привет

Другие вопросы по тегам