Comment gérer les en-têtes personnalisés avec la demande de pré-vente de CORS? AJAX – CodeIgniter

Je travaille avec CodeIgniter et l'API Restfull pour structurer l'API privée de mon serveur Web.

J'ai commencé à utiliser CORS selon les exigences pour un cadre que j'utilise.

En utilisant Jquery, je peux voir 2 demandes envoyées, la première comme type OPTION – comme prévu – mais sans mon en-tête personnalisé (X-API-KEY pour la sécurité, par défaut dans CodeIgniter Restful API).

Je reçois alors un message d'erreur de clé d'API non valide comme indiqué sur l'image. Ensuite, juste après que la requête correcte est envoyée avec des en-têtes corrects, mais en attendant, les premières requêtes ont déclenché la fonction .fail () pour gérer les erreurs.

Le premier Pre Flight Call déclenche une API KEY invalide car nous ne pouvons pas passer l'en-tête personnalisé X-API-KEY dans cet appelL'appel normal fonctionne bien

Quelle est la meilleure pratique pour gérer ce scénario? J'aimerais que ma requête ajax soit en mesure de gérer en douceur la première requête OPTION de pré-vol sans déclencher une erreur sur mon application, comme c'est le cas aujourd'hui, puis faire l'appel GET normal avec des en-têtes personnalisés selon la façon dont CORS fonctionne et exécuter l'appel de succès sans déclencher jamais l'erreur Appelez la première requête de pré-vol?

triggerFriendsWall: function() { //Get location var options = { timeout: 30000, enableHighAccuracy: true, maximumAge: 90000 }; //We need to check if user has disabled geolocation, in which case it makes the app crashes ! (from Cordova.js 1097) var position = JSON.parse(localStorage.getItem("position")); if (position == "" || position == null || position == "null" || typeof position == "undefined" ) { // In this case we have never set location to anything and the user has enabled it. navigator.geolocation.getCurrentPosition( function(position) { home.friendsWall(position); }, function(error) { common.handle_errors(error, home.friendsWall); }, options); } else { // in this case, user has disabled geolocatoin ! common.handle_errors(false, home.friendsWall); } }, friendsWall: function(position) { $.when(UserDAO.getUsersNearby(position.coords.latitude, position.coords.longitude, home.Usr_radius, home.Usr_limit, home.Usr_offset)) .done(function(response) { // Do stuff }) } getUsersNearby: function(lat, lng, radius, limit, offset) { var key = localStorage.getItem("key"); return $.ajax({ type: "GET", url: config.server_url + 'user/usersSurrounding', headers: { 'X-API-KEY': key }, data: { lat: lat, lng: lng, radius: radius, limit: limit, offset: offset }, dataType: 'json' }); }, 

Merci beaucoup

EDIT: C'est le constructeur associé à tous mes contrôleurs (tous les contrôleurs étendent un seul contrôleur où la méthode de construction est:)

 public function __construct() { header('Access-Control-Allow-Origin: *'); header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE"); $method = $_SERVER['REQUEST_METHOD']; if($method == "OPTIONS") { die(); } parent::__construct(); // $this->load->model('admin_model'); $this->load->library('session'); $this->load->library('key'); } 

Utilisez – vous Access-Control-Allow-Headers ?

Utilisé en réponse à une demande de pré-vol pour indiquer quels en-têtes HTTP peuvent être utilisés lors de la demande réelle.

Essayez d'ajouter l'en-tête suivant à votre code de pré-vol.

 header("Access-Control-Allow-Headers: content-type, origin, accept, X-API-KEY"); 

Je me souviens avoir des problèmes similaires, semblent rappeler que certains d'entre eux sont spécifiques au navigateur …

Si cela vous aide ici, un extrait d'un code que je sais fonctionne fonctionne:

 // CORS and other headers. Make sure file is not cached (as it happens for example on iOS devices) header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d MYH:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST'); header('Access-Control-Max-Age: ' . CORS_AUTH_MAX_AGE); //CORS preflight if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') { header("Access-Control-Allow-Headers: content-type, origin, accept, x-app-sig"); $acrh = explode(',', strtolower($headers['Access-Control-Request-Headers'])); foreach ($acrh as $k => $v) { $acrh[$k] = trim($v); } if (! isset($headers['Access-Control-Request-Headers']) || ! in_array('x-app-sig', $acrh)) { _log($h, '*** Bad preflight!' . PHP_EOL . print_r($headers, true) . PHP_EOL . print_r($_REQUEST, true)); header("HTTP/1.1 401 Unauthorized"); exit; //-> } _log($h, '+++ Successful preflight.' . PHP_EOL . print_r($headers, true) . PHP_EOL . print_r($_REQUEST, true)); exit; //-> } //Now we are past preflight. Actual Auth happens here, I check a signature that I post with payload. 

Mise à jour: OK, pensez mieux comprendre votre question maintenant. Publié un peu plus de code. D'abord, oui, nous faisons essentiellement la même chose là-bas. Je vérifie simplement que le pré-vol a essayé de classer en blanc ce qu'il devrait avoir en termes d'en-têtes.

Je pense que la partie dont vous avez manqué est que le pré-vol devrait / n'aura pas l'en-tête personnalisé que vous essayez d'envoyer. Voir la réponse ici: Comment envoyez-vous un en-tête personnalisé dans un XMLHttpRequest à plusieurs domaines (CORS)? ). Donc, comme je le fais, vous pouvez vérifier que le Access-Control-Request-Headers: sont envoyés avec le contrôle en amont, mais vous ne devez pas vérifier si l'en-tête réel est présent sur cet appel.

On dirait que vous avez juste besoin de déplacer un peu du code sur le côté du serveur – faites de la vanille et de la bêtise assez légère, puis faites votre authentification réelle ou vérifiez les en-têtes personnalisés après une vérification préalable réussie.

J'utilise une signature HMAC envoyée avec la charge utile moi-même pour authentifier les choses après le pré-vol. Je vérifie également que la x-app-sig personnalisée est fournie et ce que je m'attends, même si cela est probablement redondant.

Je fais du duel avec ce problème depuis deux jours. Il sort, en fin de compte, il doit y avoir un flux pour ces réquisitions et il est simple. D'abord, vous devez autoriser les champs d'en-tête qui sont envoyés (avec tous les en-têtes CORS), dans mon cas, c'était:

 <?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Allow-Headers: authorization, content-type, x-requested-with'); 

Ensuite, j'ai tout simplement dû renvoyer le statut "204 Pas de Contenu" chaque fois qu'une méthode OPTIONS de demande est arrivée. Vous pouvez utiliser une déclaration de condition comme suit:

 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('HTTP/1.1 204 No Content'); }