50 votes

Demande Ajax HTTP via une page HTTPS

J'ai un site dont certaines pages sont en connexion HTTPS. À partir de ces pages HTTPS, je dois utiliser une requête Ajax HTTP pour récupérer certaines erreurs comme des champs vides. Mais ces messages d'erreur n'apparaissent pas. Y a-t-il une solution ou dois-je faire cette demande AJAX pour le fichier sur la connexion HTTPS ?

0 votes

Ajax devrait fonctionner correctement sur https, pouvez-vous poster votre extrait de code actuel ?

2 votes

Cela ressemble à une SOP ( fr.wikipedia.org/wiki/Same_origin_policy ) : les schémas sont différents, il s'agit donc d'une origine différente.

0 votes

Merci pour la réponse. J'ai modifié mon site web en conséquence.

58voto

Pekka 웃 Points 249607

Cela n'est pas possible en raison de la Politique de l'origine identique .

Vous devrez également passer les requêtes Ajax en https.

2 votes

Même l'avant-projet de partage des ressources entre origines rend la chose impossible : w3.org/TR/cors/#user-agent-security

0 votes

Merci à tous pour la réponse. J'ai modifié mon site web en fonction de la politique de la même origine.

2 votes

@NickSotiros Pourquoi ne pas vouloir le sécuriser ? Il n'y a aucun inconvénient, et les requêtes HTTP sur une page HTTPS pourraient potentiellement être attaquées par un MITM pour injecter un JS malveillant.

15voto

Endless Points 1188

Sans solution côté serveur, il n'y a qu'un seul moyen pour qu'une page sécurisée puisse obtenir quelque chose d'une page/requête non sécurisée, et c'est par le biais de postMessage et d'une popup.

J'ai dit popup parce que le site n'est pas autorisé à mélanger le contenu. Mais une popup n'est pas vraiment un mélange. Elle a sa propre fenêtre mais elle est toujours capable de communiquer avec l'ouvreur avec postMessage.

Vous pouvez donc ouvrir une nouvelle page http avec window.open(...) et que cela fasse la demande pour vous


XDomain m'est venu à l'esprit quand j'ai écrit ceci mais voici une approche moderne utilisant la nouvelle récupérer l'api l'avantage est le streaming de fichiers volumineux, l'inconvénient est qu'il ne fonctionne pas dans tous les navigateurs.

Vous mettez ce proxy script sur n'importe quelle page 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()
  })
}

Ensuite, vous ouvrez une fenêtre popup dans votre page https (notez que vous ne pouvez le faire que sur un événement d'interaction avec l'utilisateur, sinon il sera bloqué).

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

créer votre fonction utilitaire

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

Et faites la demande comme vous le faites normalement avec l'api fetch.

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

5voto

Maxim Ilin Points 41

Pourtant, cela peut être fait en suivant les étapes suivantes :

  1. envoyer une requête ajax https à votre site web (le même domaine)

    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. obtenir une requête ajax, par exemple, par php, et faire une requête CURL get vers n'importe quel site web souhaité via http.

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

1 votes

Ce concept a parfaitement fonctionné (en utilisant le code correspondant à mon installation/projet). J'ai créé un fichier php sur mon serveur et fait une requête curl sur une URL HTTP. J'ai appelé ce fichier depuis mon site web HTTPS et j'ai envoyé la variable dont j'avais besoin pour l'API et voilà !

0 votes

Je ne connais que le point final, comment utiliser cette méthode pour mon site web. Mon site web est https et l'API est http://5ty.org:8080/api/card/post

0 votes

L'inconvénient est que si votre page fait l'objet de nombreuses demandes simultanées, vous risquez de saturer votre serveur.

3voto

user2080851 Points 229

Dans certains cas, une requête unidirectionnelle sans réponse peut être envoyée à un serveur TCP, sans certificat SSL. Un serveur TCP, contrairement à un serveur HTTP, captera votre demande. Cependant, il n'aura pas accès aux données envoyées par le navigateur, car ce dernier n'enverra pas de données sans une vérification positive du certificat. Dans certains cas, même un signal TCP nu, sans données, est suffisant pour exécuter certaines tâches. Par exemple, pour un appareil IoT au sein d'un réseau local, pour lancer une connexion à un service externe. Lien

Il s'agit d'une sorte de déclencheur "Wake Up", qui fonctionne sur un port sans aucune sécurité.

Si une réponse est nécessaire, elle peut être mise en œuvre en utilisant un serveur https public sécurisé, qui peut renvoyer les données nécessaires au navigateur en utilisant, par exemple, des Websockets.

2voto

Nikita Khanna Points 11

Créer une API de contournement dans server.js. Cela fonctionne pour moi.

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

Et appelez-le en utilisant axios ou fetch comme ceci :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X