AngularJS $ http, CORS dan otentikasi http

87

Karena menggunakan otentikasi CORS dan http dengan AngularJS bisa rumit, saya mengedit pertanyaan untuk berbagi satu pelajaran yang dipelajari. Pertama saya ingin berterima kasih kepada igorzg. Jawabannya sangat membantu saya. Skenarionya adalah sebagai berikut: Anda ingin mengirim permintaan POST ke domain yang berbeda dengan layanan AngularJS $ http. Ada beberapa hal rumit yang harus diperhatikan saat mendapatkan AngularJS dan penyiapan server.

Pertama: Dalam konfigurasi aplikasi Anda, Anda harus mengizinkan panggilan lintas domain

/**
 *  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;
});

Kedua: Anda harus menentukan withCredentials: true dan nama pengguna dan kata sandi yang diminta.

 /**
  *  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'
        }
    });

Ketiga: Penyiapan server. Anda harus menyediakan:

/**
 *  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");

Untuk setiap permintaan. Ketika Anda menerima OPTION, Anda harus lulus:

/**
 *  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();
}

Otentikasi HTTP dan yang lainnya muncul setelah itu.

Berikut adalah contoh lengkap penggunaan sisi server dengan 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();
}
?>

Ada artikel di blog saya tentang masalah ini yang bisa dilihat di sini .

Georgi Naumov
sumber
Pertanyaannya sudah diedit.
Georgi Naumov
2
Saya agak bingung, ini angularjs tetapi Anda membungkusnya dengan tag PHP .... apakah saya melewatkan sesuatu?
onaclov2000
Ini hanyalah contoh logika sisi server. Teks di bawah "Тhird: Server setup" adalah logika sisi server.
Georgi Naumov
@ onaclov2000 AngularJS adalah untuk sisi klien. Ini dapat berbicara ke sisi server mana pun, PHP, Ruby, Perl, Python, Java, JavaScript ... Saya bisa melanjutkan ..
Eric Hodonsky
1
Apakah ini pertanyaan? Ini lebih seperti jawaban yang bagus :)
Mohammad Kermani

Jawaban:

43

Tidak, Anda tidak perlu memasukkan kredensial, Anda harus meletakkan header di sisi klien, misalnya:

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

Dan di sisi server Anda harus meletakkan header untuk ini, contoh untuk 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();
    }


});
igorzg.dll
sumber
dengan CORS secara umum, apakah server harus mengizinkan semua header (Konten, Panjang Konten, Referer, dll ...) yang ada dalam permintaan nyata, yaitu non-OPTIONS?
Kevin Meredith
@KevinMeredith Tidak, Anda tidak harus mengizinkan semua header, Anda hanya dapat mengizinkan apa yang Anda butuhkan dan Anda bahkan dapat membatasi juga ke satu domain.
igorzg
1
bagaimana saya tahu apa yang saya butuhkan?
Kevin Meredith
Terima kasih atas jawaban Anda yang bagus :)
Kamruzzaman
1
Saya bingung, mengapa saya tidak perlu mengautentikasi dengan titik akhir jika diamankan dengan otentikasi dasar http?
Maxim Zubarev
3

Untuk membuat permintaan CORS seseorang harus menambahkan header ke permintaan bersama dengan yang sama dia perlu memeriksa mode_header diaktifkan di Apache.

Untuk mengaktifkan header di Ubuntu:

sudo a2enmod headers

Agar server php menerima permintaan dari sumber yang berbeda, gunakan:

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"
Vijay Kumar
sumber