web-dev-qa-db-fra.com

AngularJS $ http, CORS et authentification http

Parce que l'utilisation de l'authentification CORS et http avec AngularJS peut être délicate, j'ai modifié la question pour partager une leçon apprise. Je veux d'abord remercier igorzg. Sa réponse m'a beaucoup aidé. Le scénario est le suivant: Vous souhaitez envoyer la demande POST à un autre domaine avec le service AngularJS $ http. Il y a plusieurs choses délicates à prendre en compte pour obtenir AngularJS et la configuration du serveur.

Premièrement: dans votre configuration d’application, vous devez autoriser les appels entre domaines.

/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  [email protected] for contacts and 
 *  suggestions. 
 **/ 
app.config(function($httpProvider) {
    //Enable cross domain calls
    $httpProvider.defaults.useXDomain = true;
});

Deuxièmement: Vous devez spécifier withCredentials: true et le nom d'utilisateur et le mot de passe dans request.

 /**
  *  Cors usage example. 
  *  @author Georgi Naumov
  *  [email protected] for contacts and 
  *  suggestions. 
  **/ 
   $http({
        url: 'url of remote service',
        method: "POST",
        data: JSON.stringify(requestData),
        withCredentials: true,
        headers: {
            'Authorization': 'Basic bashe64usename:password'
        }
    });

Troisième: Configuration du serveur. Vous devez fournir:

/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  [email protected] for contacts and 
 *  suggestions. 
 **/ 
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://url.com:8080");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

Pour chaque demande Lorsque vous recevez une OPTION, vous devez passer:

/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  [email protected] for contacts and 
 *  suggestions. 
 **/ 
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
   header( "HTTP/1.1 200 OK" );
   exit();
}

L'authentification HTTP et tout le reste vient ensuite.

Voici un exemple complet d'utilisation du côté serveur avec php.

<?php
/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  [email protected] for contacts and 
 *  suggestions. 
 **/ 
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://url:8080");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
   header( "HTTP/1.1 200 OK" );
   exit();
}


$realm = 'Restricted area';

$password = 'somepassword';

$users = array('someusername' => $password);


if (isset($_SERVER['PHP_AUTH_USER']) == false ||  isset($_SERVER['PHP_AUTH_PW']) == false) {
    header('WWW-Authenticate: Basic realm="My Realm"');

    die('Not authorised');
}

if (isset($users[$_SERVER['PHP_AUTH_USER']]) && $users[$_SERVER['PHP_AUTH_USER']] == $password) 
{
    header( "HTTP/1.1 200 OK" );
    echo 'You are logged in!' ;
    exit();
}
?>

Il y a un article sur mon blog à ce sujet qui peut être vu ici .

88
Georgi Naumov

Non, vous n'avez pas à mettre les informations d'identification, vous devez mettre les en-têtes côté client, par exemple:

 $http({
        url: 'url of service',
        method: "POST",
        data: {test :  name },
        withCredentials: true,
        headers: {
                    'Content-Type': 'application/json; charset=utf-8'
        }
    });

Et du côté du serveur, vous devez mettre des en-têtes. C'est un exemple pour nodejs:

/**
 * On all requests add headers
 */
app.all('*', function(req, res,next) {


    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.Origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

    if ('OPTIONS' == req.method) {
        res.send(200);
    }
    else {
        next();
    }


});
43
igorzg

Pour faire une demande CORS, il faut ajouter des en-têtes à la demande avec le même dont il a besoin pour vérifier si mode_header est activé dans Apache.

Pour activer les en-têtes dans Ubuntu:

Sudo a2enmod headers

Pour que le serveur php accepte les requêtes provenant d’usages d’origine différents:

Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, Origin, authorization, accept, client-security-token"
3
Vijay Kumar