AngularJS $ http, CORS e autenticazione http


87

Poiché l'utilizzo di CORS e dell'autenticazione http con AngularJS può essere complicato, ho modificato la domanda per condividere una lezione appresa. Per prima cosa voglio ringraziare igorzg. La sua risposta mi ha aiutato molto. Lo scenario è il seguente: si desidera inviare una richiesta POST a un dominio diverso con il servizio http di AngularJS $. Ci sono molte cose difficili da tenere presenti quando si ottiene AngularJS e la configurazione del server.

Primo: nella configurazione dell'applicazione è necessario consentire la chiamata interdominio

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

Secondo: è necessario specificare withCredentials: true e nome utente e password nella richiesta.

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

Terzo: configurazione del server. Devi fornire:

/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  gonaumov@gmail.com 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");

Per ogni richiesta. Quando ricevi OPTION devi superare:

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

L'autenticazione HTTP e tutto il resto viene dopo.

Ecco un esempio completo di utilizzo del lato server con php.

<?php
/**
 *  Cors usage example. 
 *  @author Georgi Naumov
 *  gonaumov@gmail.com 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();
}
?>

C'è un articolo sul mio blog su questo problema che può essere visto qui .


La domanda viene modificata.
Georgi Naumov

2
Sono un po 'confuso, è angularjs ma lo hai racchiuso in tag PHP .... mi sono perso qualcosa?
onaclov2000

Questo è solo un esempio di logica lato server. Il testo sotto "Terzo: Configurazione del server" è la logica lato server.
Georgi Naumov

@ onaclov2000 AngularJS è per il lato client. Questo può parlare con qualsiasi lato server, PHP, Ruby, Perl, Python, Java, JavaScript ... Potrei andare avanti ..
Eric Hodonsky

1
Questa è una domanda? È più come una buona risposta :)
Mohammad Kermani

Risposte:


43

No, non devi inserire le credenziali, devi mettere le intestazioni sul lato client es:

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

E sul lato server devi mettere le intestazioni in questo esempio per 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();
    }


});

con CORS in generale, il server deve consentire tutte le intestazioni (Content, Content-Length, Referer, ecc ...) presenti nella richiesta reale, cioè non OPTIONS?
Kevin Meredith

@KevinMeredith No, non devi consentire tutte le intestazioni, puoi consentire solo ciò di cui hai bisogno e puoi persino limitare anche a un dominio.
igorzg

1
come faccio a sapere di cosa ho bisogno?
Kevin Meredith

Grazie per la tua bella risposta :)
Kamruzzaman

1
Sono confuso, perché non ho bisogno di autenticarmi con l'endpoint se è protetto da un'autenticazione di base http?
Maxim Zubarev,

3

Per effettuare una richiesta CORS è necessario aggiungere intestazioni alla richiesta insieme alle stesse di cui ha bisogno per verificare che mode_header sia abilitato in Apache.

Per abilitare le intestazioni in Ubuntu:

sudo a2enmod headers

Affinché il server php accetti richieste provenienti da origini diverse, utilizzare:

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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.