Este sigur să rezolvi erorile Access-Control-Allow-Origin (CORS origin) cu o directivă header PHP?
Încerc să afișez un formular Formidable Pro de pe un site WordPress pe un alt site. Am urmat documentația dezvoltatorului și REST API, dar m-am confruntat cu o problemă CORS.
Apoi am găsit o sugestie într-un thread pe forum care propunea adăugarea acestei linii de cod în functions.php
al site-ului unde se află formularul original:
header("Access-Control-Allow-Origin: *");
Am încercat acest cod și a funcționat perfect.
Întrebarea mea este: acest cod creează riscuri de securitate sau alte vulnerabilități?
Soluția pare prea simplă pentru o problemă cu care se confruntă mulți oameni.
Apreciez foarte mult părerea voastră.
Da, deschizi site-ul tău pentru a fi accesat prin AJAX de către orice alt script de pe întregul internet.
Ar fi mai bine să limitezi originea la un singur domeniu specific de la care consumi API-ul, ca în acest exemplu:
header("Access-Control-Allow-Origin: http://mozilla.com");
Totuși, după cum menționează documentația Mozilla, un client poate falsifica originea, dar limitarea site-urilor la care un utilizator obișnuit se poate conecta reprezintă un obstacol pentru unele atacuri.
Și mai bine, poți limita cererile doar la metodele pe care chiar trebuie să le permiți, esența este acest fragment de cod, care funcționează pentru mai multe domenii, dacă variabila $_SERVER['HTTP_ORIGIN']
este populată:
add_action('rest_api_init', function() {
/* dezactivează funcția implicită */
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
/* adaugă propriul filtru */
add_filter('rest_pre_serve_request', function( $value ) {
$origin = get_http_origin();
$my_sites = array( 'http://site1.org/', 'http://site2.net', );
if ( in_array( $origin, $my_sites ) ) {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
} else {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
}
header( 'Access-Control-Allow-Methods: GET' );
return $value;
});
}, 15);
După cum poți vedea, acest fragment utilizează funcția get_http_origin oferită de WordPress, dar va returna null sau gol dacă cheia HTTP_ORIGIN
nu este populată în array-ul $_SERVER
, deci nu este disponibilă scriptului PHP, poate pentru că este blocată de proxy-ul Cloudflare pe care îl folosești. Aș verifica rapid, cu un script care conține <?php phpinfo(); ?>
, dacă această variabilă este populată.
Poate că site-ul de origine este populat într-un alt header de către Cloudflare și ai putea să-l folosești într-o funcție conectată la filtrul http_origin
. Dacă ești blocat până în acest punct, editează întrebarea inițială postând conținutul variabilei _SERVER, cu excepția câmpurilor ce conțin parole sau căi de sistem.
Aș fi bucuros să te ajut.

Mulțumesc. Prima soluție a funcționat pentru mine. Dar având în vedere că am 4 site-uri pe care vreau să le permit accesul la site-ul principal, trebuie să repet linia de 4 ori și să schimb URL-ul site-ului, sau pot fi combinate într-o singură comandă? Mulțumesc.

Bineînțeles că poți, eu obișnuiesc să permit accesul la API doar pentru câteva site-uri. Am actualizat răspunsul meu cu verificarea pentru acest lucru. Dacă funcționează, ai putea să votezi răspunsul?

prima soluție a funcționat doar pentru 1 domeniu. dacă am repetat linia, nu a funcționat. Am încercat metoda din acest thread link, dar nu a funcționat nici aceea.
Când am aplicat soluția 2, iată ce am primit: XMLHttpRequest cannot load https://coptic-treasures.com/wp-json/frm/v2/forms/6?return=html. The 'Access-Control-Allow-Origin' header has a value 'https://coptic-treasures.com' that is not equal to the supplied origin. Origin 'https://audio.coptic-treasures.com' is therefore not allowed access.

Nu poți folosi header-ul Allow Origin de mai multe ori. Am actualizat răspunsul meu cu instrucțiuni suplimentare pentru a te ajuta să depanezi problema, deoarece returnarea mereu a aceluiași site nu ar trebui să se întâmple și ar trebui să recunoască lista de domenii pe care o transmiți în array. Te rog să actualizezi întrebarea ta cu datele din variabila $_SERVER, returnate de phpinfo()
, excluzând parolele și căile de sistem de fișiere. Aș fi bucuros să te ajut.

Mi-a luat cam 2 zile să aflu cum să elimin accesul CORS din API-ul WP-JSON. Mulțumesc pentru asta. Elimină apelul funcției rest_send_cors_headers
!

context - browserele restricționează accesul la distanță din scripturi doar pentru site-ul de pe care a fost încărcat. Dacă acest tip de verificare nu ar fi făcut, în timp ce vizitați un site X, ar fi posibil ca acesta să trimită date în contul dvs. Gmail (dacă sunteți conectat) fără să fie nevoie să ghicească numele de utilizator și parola, deoarece browserul ar fi trimis cookie-urile corespunzătoare de autentificare către Gmail.
Protocolul CORS este conceput să vă ajute să relaxați această restricție atunci când este necesar.
Deci întrebarea pe care ar trebui să v-o puneți este: am nevoie de asta? Pe de o parte, nu văd de ce 99% dintre site-urile WordPress ar avea nevoie de această funcționalitate, pe de altă parte, cookie-urile WordPress au o durată de viață relativ scurtă și 99% dintre site-urile WordPress nu vor fi ținte pentru un astfel de atac aleatoriu.
Aș spune că, deoarece REST API este unul care permite modificări și are acces la informații private, nu ar trebui să utilizați REST API în soluția dvs. dacă trebuie să activați CORS, este mai bine să vă creați propriul API "doar pentru citire".

OP nu vorbește despre 99% dintre site-urile WP existente, ci despre propriile site-uri, iar conform întrebării, este necesar să se facă disponibile resurse de pe alt site.

Că ideea este să răspunzi la întrebare, acesta este scopul acestui site.

@JesúsFranco, cred că reputația mea arată că știu cum să răspund la întrebări și nu am nevoie de sfaturile tale?

Deci, ai o idee anume despre cum OP poate rezolva această problemă?

@JesúsFranco, OP a întrebat dacă este sigur. Răspunsul este că nu este. Soluția evidentă este să nu faci lucruri care să necesite utilizarea CORS

Întrebarea mea se bazează pe faptul că menționați că există un risc de acces la informații private. De fapt, unul dintre principiile de bază ale API-ului este că doar dezvoltatorul poate acorda acces la informații private, deoarece API-ul în forma sa originală nu oferă acest lucru.

@JesúsFranco Din câte știu eu, API-ul folosește cookie-uri pentru autentificare și persoanele cu rol de admin, de exemplu, pot obține aproape orice informație. Dacă CORS este complet dezactivat și eu folosesc un fel de phishing pentru a vă atrage pe site-ul meu, pot scrie un cod JS care va executa orice operație pe site-ul dumneavoastră, deoarece sunteți autentificat în el iar browserul dumneavoastră va trimite cookie-urile de autentificare ca parte a cererii. Nici măcar nu va trebui să ghicesc numele de utilizator... Nu este suficient nici măcar să blochezi accesul la punctele finale de "scriere", deoarece ca admin poți obține informații clasificate.

Este posibil ca în prezent să nu fie multe lucruri care pot fi obținute cu API-ul, dar scopul său este să poată înlocui întreaga interfață de administrare, așa că va trebui să servească clientului toate datele existente.

Mulțumesc Mark, cunoașterea mecanismului care poate fi abuzat pentru a transforma accesul la API în ceva nesigur, este foarte utilă pentru a gândi cum să gestionăm acele riscuri, iar apoi pentru a putea decide dacă poate fi folosit un patch, limitând în alte moduri utilizările metodelor disponibile pentru scripturile la distanță, sau pentru a scrie un API complet nou.

@MarkKaplun Sunt nou în WP-API, așa că am o întrebare. Permiterea CORS doar pentru metodele 'GET' ar expune și serverul la vulnerabilități?

@shariqkhan, aceasta este probabil mai bine întrebată pe SO sau pe stack-ul de securitate, dar în general, răspunsul este da. CORS ar trebui dezactivat doar pentru site-uri în care aveți încredere sau pe subdomenii ale dvs. care nu efectuează nicio acțiune fără a trimite credențiale de autorizare în corpul cererii. Atâta timp cât restul API-ului folosește cookie-uri pentru autentificare și rulează pe același domeniu ca site-ul WP, ar trebui să fiți foarte atenți cu dezactivarea acestuia.

dar din nou, dacă dezactivezi CORS doar pentru un URL specific despre care știi că nu poate fi folosit pentru a face vreun rău, atunci ar putea fi OK. Nu este atât de mult o problemă de GET vs POST, ci mai degrabă despre ce se întâmplă de fapt la acel endpoint

Mulțumesc @MarkKaplun, am văzut multe dintre răspunsurile tale pe SO/SE așa că știu că știi despre ce vorbești, probabil voi întreba pe SO, deși simt că întrebarea ar putea fi închisă ca fiind „prea largă” sau ca „duplicat”. Sunt intrigat de modul în care diverse site-uri web precum Github, Twitter (și multe site-uri bazate pe WordPress de asemenea) își deschid API-urile prin dezactivarea restricțiilor CORS pentru toată lumea. Am crezut că dacă dezactivezi CORS doar pentru cererile GET, este destul de inofensiv pentru că doar permiți altora să preia date și nu modifici nimic?

Diferența dintre WordPress și alte site-uri este că acestea nu folosesc autentificare bazată pe cookie-uri pentru API, iar utilizarea API-ului necesită trimiterea explicită a informațiilor de utilizator și parolă în fiecare cerere. API-ul WordPress <alertă rant> a fost prost conceput în acest sens și probabil nu a putut fi proiectat mai bine deoarece trebuia să suporte comunicarea nesigură prin HTTP, ceea ce l-a împiedicat să utilizeze tehnica utilizator/parolă, deoarece oricine asculta pe o rețea (de exemplu) WiFi ar fi putut descoperi valorile.

faptul că ai cookie-urile setate când ești autentificat este ceea ce atacatorii pot exploata pentru a trimite cereri AJAX ca și cum ar fi inițiate de tine. Cu CORS activat, astfel de cereri vor eșua pentru alte domenii, iar din moment ce tu ești singurul care controlează domeniul, ești în siguranță. Cu cât dezactivezi CORS pentru mai multe site-uri, cu atât mai multe locuri există unde un atacator poate prelua controlul și să te atragă să accesezi acel site. Întrebarea era despre dezactivarea completă a CORS pentru toate site-urile, ceea ce este foarte periculos, dar dacă îl dezactivezi pentru alte domenii pe care le controlezi în totalitate, deși nu este ideal, nu este la fel de rău.
