web-dev-qa-db-fra.com

jQuery AJAX L'appel entraîne un état d'erreur 403

Je pose une requête à un service Web utilisant jQuery AJAX. Ma requête ressemble à ceci:

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'jsonp',
  contentType: 'jsonp',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

Lorsque j'exécute cette opération, j'obtiens une erreur d'état de 403. Je ne comprends pas pourquoi mon appel entraîne le code d'état 403. Je contrôle la sécurité de mon service et elle est marquée comme grande ouverte. Je sais que la clé est valide, car je l’utilise dans un autre appel, ce qui fonctionne. Voici l'appel qui fonctionne:

var endpoint = 'http://example.com/object/data/item?version=1.1';
$.ajax({ 
  type: 'POST', 
  url: endpoint, 
  cache: 'false',
  contentType:'application/json',
  headers: {
    'api-key':'myKey',
    'Content-Type':'application/json'
  },
  data: JSON.stringify({
    id: 5,
    count:true
  }),
  success: onDataSuccess,
  error: onDataFailure
});

Je sais que ce sont deux points de terminaison différents. Mais je suis convaincu à 100% qu'il ne s'agit pas d'une erreur d'authentification ou de permission côté serveur. Encore une fois, tout est grand ouvert côté serveur. Ce qui implique que je commets une erreur sur ma demande côté client.

Je pense que je devrais communiquer que cette demande est en cours de développement. Donc, je lance ceci à partir de http: // localhost: 3000 . Pour cette raison, j'ai immédiatement supposé que c'était un problème de la SCRO. Mais tout semble correct. Le fait que ma POST demande fonctionne, mais que ma fonction GET ne me laisse pas absolument frustré. Est-ce que je manque quelque chose? Qu'est ce que ça pourrait être?

11
Zach Templeton

La raison de l'erreur 403 est vous n'envoyez pas les en-têtes. Puisque vous faites une demande CORS, vous ne pouvez pas envoyer d’en-têtes personnalisés à moins que le serveur les active en ajoutant Access-Control-Allow-Headers à la réponse.

Dans un preflighted-request , le client adresse 2 requêtes au serveur. Le premier est le contrôle en amont (avec la méthode OPTION) et le second est la demande réelle. Le serveur envoie Access-Control-Allow-Headers en-tête en réponse à la demande de contrôle en amont. Cela permet donc d’envoyer des en-têtes. De cette manière, votre demande POST peut fonctionner, car la demande POST est une demande avec contrôle en amont. Mais pour une demande GET, il n'y a pas de contrôle en amont à rassembler Access-Control-Allow-Headers header. Donc, le navigateur n'envoie pas vos en-têtes personnalisés.

Une solution de contournement pour ce problème:

Pour résoudre ce problème, définissez votre dataType et contentType sur json comme suit:

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'json',
  contentType: 'json',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

De cette manière, votre demande d’obtention sera un preflighted request. Si votre serveur active le api-key avec en-tête/Access-Control-Allow-Headers , cela fonctionnera.

Exemple de configuration de serveur pour la requête ci-dessus (écrite dans express.js):

res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader('Access-Control-Allow-Headers', 'api-key,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);

AJOUTÉE:

En fait, contentType devrait être application/javascript ou application/json lors d’une requête jsonp. Il n'y a pas contentType comme jsonp.

17
ykaragol

Si vous consultez la page API pour l'appel Ajax de jQuery, les éléments suivants sont mentionnés dans la section Content-Type:

Remarque: Pour les demandes interdomaines, définissez le type de contenu sur n'importe quoi autre que application/x-www-form-urlencoded, multipart/form-data ou text/plain déclenchera le navigateur pour envoyer un contrôle en amont OPTIONS. demande au serveur.

Cette page ne mentionne pas vraiment ce qu'est une "demande OPTION de contrôle en amont", mais j'ai trouvé des liens intéressants en cherchant cette phrase en ligne:

Ce qui est intéressant, c’est l’exemple de code et l’image CORS de la page HTML5Rocks. L'image montre comment les appels Ajax sont effectués à partir du code JavaScript vers le navigateur vers le serveur et comment les réponses sont arrondies entre les trois. 

Nous avons tendance à penser à JavaScript + Navigateur = Client, mais dans l'illustration, l'auteur explique la différence entre le code du développeur Web et le code du développeur de navigateur, où le premier est écrit en code JavaScript, mais le dernier a été écrit en C, C++ ou code C #. 

Un bon outil d'analyse de paquets est Fiddler , qui serait semblable à Wireshark . L'un ou l'autre de ces outils devrait vous montrer les demandes de pré-vol qui sont envoyées du navigateur au serveur. Très probablement, c'est là que votre demande Ajax est bloquée par le serveur avec une erreur 403 Forbidden .

0
Clomp