Hoe werkt de Access-Control-Allow-Origin-header?

Blijkbaar heb ik de semantiek volledig verkeerd begrepen. Ik dacht aan zoiets als dit:

  1. Een client downloadt javascript-code MyCode.js van http://siteAde oorsprong.
  2. De responsheader van MyCode.js bevat Access-Control-Allow-Origin: http://siteB, wat volgens mij betekende dat MyCode.js maak cross-origin verwijzingen naar de site B.
  3. De client activeert een bepaalde functionaliteit van MyCode.js, die op zijn beurt verzoeken doet aan http://siteB, wat in orde zou moeten zijn, ondanks dat het om cross-origin-verzoeken gaat.

Nou, ik heb het mis. Zo werkt het helemaal niet. Dus ik heb Cross-origin resource sharinggelezen en geprobeerd Cross-Origin Resource Sharing in w3c-aanbeveling

Eén ding is zeker: ik begrijp nog steeds niet hoe ik deze header moet gebruiken.

Ik heb volledige controle over zowel site A als site B. Hoe schakel ik de javascript-code die is gedownload van site A in om toegang te krijgen tot bronnen op site B met behulp van deze header?

P.S.

Ik wil JSONP niet gebruiken.


Antwoord 1, autoriteit 100%

Access-Control-Allow-Originis een CORS (Cross -Origin Resource Sharing) koptekst.

Wanneer site A inhoud probeert op te halen van site B, kan site B een Access-Control-Allow-Origin-reactieheader sturen om de browser te vertellen dat de inhoud van deze pagina toegankelijk is voor bepaalde bronnen . (Een oorsprongis een domein, plus een schema en poortnummer.) Standaard is Site B’s pagina’s zijn niet toegankelijk voor een andere oorsprong; het gebruik van de Access-Control-Allow-Origin-header opent een deur voor cross-origin-toegang door specifieke verzoekende oorsprongen.

Voor elke bron/pagina die site B toegankelijk wil maken voor site A, moet site B zijn pagina’s voorzien van de antwoordkop:

Access-Control-Allow-Origin: http://siteA.com

Moderne browsers zullen verzoeken tussen domeinen niet rechtstreeks blokkeren. Als Site A een pagina opvraagt van Site B, zal de browser de gevraagde pagina daadwerkelijk ophalen op netwerkniveauen controleren of de antwoordheaders Site A als een toegestaan domein van de aanvrager weergeven. Als site B niet heeft aangegeven dat site A toegang heeft tot deze pagina, activeert de browser de XMLHttpRequest‘s error-gebeurtenis en weigert de responsgegevens voor de verzoekende JavaScript-code .

Niet-eenvoudige verzoeken

Wat er op netwerkniveau gebeurt, kan ietsingewikkelder zijn dan hierboven uitgelegd. Als het verzoek een “niet- eenvoudig” verzoek, stuurt de browser eerst een gegevensloos “preflight” OPTIONS-verzoek om te controleren of de server het verzoek accepteert. Een verzoek is niet eenvoudig als een van beide (of beide):

  • een ander HTTP-werkwoord gebruiken dan GET of POST (bijv. PUT, DELETE)
  • het gebruik van niet-eenvoudige verzoekheaders; de enige eenvoudige verzoekheaders zijn:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(dit is alleen eenvoudig als de waarde application/x-www-form-urlencoded, multipart/form-data, of text/plain)

Als de server reageert op de OPTIONS-preflight met de juiste antwoordheaders (Access-Control-Allow-Headersvoor niet-eenvoudige headers, Access-Control-Allow-Methodsvoor niet-eenvoudige werkwoorden) die overeenkomen met het niet-eenvoudige werkwoord en/of niet-eenvoudige headers, dan verzendt de browser het daadwerkelijke verzoek.

Stel dat Site A een PUT-verzoek wil verzenden voor /somePage, met een niet-eenvoudige Content-Type-waarde van application/jsonzou de browser eerst een preflight-verzoek sturen:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Merk op dat Access-Control-Request-Methoden Access-Control-Request-Headersautomatisch door de browser worden toegevoegd; u hoeft ze niet toe te voegen. Deze OPTIONS-preflight krijgt de succesvolle responsheaders:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

Bij het verzenden van het daadwerkelijke verzoek (nadat de preflight is voltooid), is het gedrag identiek aan hoe een eenvoudig verzoek wordt afgehandeld. Met andere woorden, een niet-eenvoudig verzoek waarvan de preflight succesvol is, wordt op dezelfde manier behandeld als een eenvoudig verzoek (dwz de server moet nog steeds Access-Control-Allow-Originopnieuw verzenden voor het daadwerkelijke antwoord).

De browser verzendt het daadwerkelijke verzoek:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json
{ "myRequestContent": "JSON is so great" }

En de server stuurt een Access-Control-Allow-Originterug, net zoals bij een eenvoudig verzoek:

Access-Control-Allow-Origin: http://siteA.com

Zie Inzicht in XMLHttpRequest over CORSvoor wat meer informatie over niet-eenvoudige verzoeken.


Antwoord 2, autoriteit 8%

Cross-Origin Resource Sharing – CORS(ook bekend als Cross-Domain AJAX-verzoek) is een probleem dat de meeste webontwikkelaars kunnen tegenkomen, volgens Same-Origin-Policy, browsers beperken client-JavaScript in een beveiliging sandbox, kan JS meestal niet rechtstreeks communiceren met een externe server van een ander domein. In het verleden hebben ontwikkelaars veel lastige manieren bedacht om een verzoek om bronnen voor meerdere domeinen te doen. De meest gebruikte manieren zijn:

  1. Gebruik Flash/Silverlight of serverzijde als een “proxy” om te communiceren
    met afstandsbediening.
  2. JSON met opvulling (JSONP).
  3. Sluit externe server in een iframe in en communiceert via fragment of window.name, zie hier.

Die lastige manieren hebben min of meer enkele problemen, JSONP kan bijvoorbeeld resulteren in een beveiligingslek als ontwikkelaars het gewoon “evalueren”, en #3 hierboven, hoewel het werkt, zouden beide domeinen een strikt contract tussen elkaar moeten bouwen, het geen van beide flexibel noch elegant IMHO 🙂

W3C had Cross-Origin Resource Sharing (CORS) geïntroduceerd als een standaardoplossing om een veilige, flexibele en aanbevolen standaardmanier te bieden om dit probleem op te lossen.

Het mechanisme

Van een hoog niveau kunnen we eenvoudigweg aannemen dat CORS een contract is tussen een AJAX-oproep van een klant van domein A en een pagina die wordt gehost op domein B, een typisch Cross-Origin-verzoek/-antwoord zou zijn:

DomeinA AJAX-verzoekheaders

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

DomeinB-reactieheaders

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

De blauwe delen die ik hierboven heb gemarkeerd waren de kernal feiten, “Origin” verzoek header “geeft aan waar het cross-origin verzoek of preflight verzoek vandaan komt”, de “Access-Control-Allow-Origin” antwoordheader geeft aan dat deze pagina dit toestaat extern verzoek van DomainA (als de waarde * is, geeft u aan dat externe verzoeken van elk domein zijn toegestaan).

Zoals ik hierboven al zei, raadde W3 de browser aan om een “preflightverzoek” te implementeren voordat het daadwerkelijke Cross-Origin HTTP-verzoek wordt ingediend, in een notendop is het een HTTP OPTIONSverzoek:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Als foo.aspx het OPTIONS HTTP-werkwoord ondersteunt, kan het een antwoord geven zoals hieronder:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Alleen als het antwoord “Access-Control-Allow-Origin” bevat EN de waarde “*” is of het domein bevat dat het CORS-verzoek heeft ingediend, door aan deze verplichte voorwaarde te voldoen, zal de browser het daadwerkelijke Cross-Domain-verzoek indienen, en cache het resultaat in “Preflight-Result-Cache“.

Ik heb drie jaar geleden over CORS geblogd: AJAX Cross-Origin HTTP-verzoek


Antwoord 3, autoriteit 5%

Vraag is een beetje te oud om te beantwoorden, maar ik plaats dit voor eventuele toekomstige verwijzing naar deze vraag.

Volgens ditartikel in Mozilla Developer Network,

Een bron doet een cross-origin HTTP-verzoekwanneer het een bron aanvraagt van een ander domein of poort dan degene die de eerste bron zelf bedient.

voer hier de afbeeldingsbeschrijving in

Een HTML-paginageserveerd vanaf http://domain-a.comdoet een <img>src-verzoek voor http://domain-b.com/image.jpg.
Veel pagina’s op het web laden bronnen zoals CSS-stylesheets, afbeeldingenen scriptsvan afzonderlijke domeinen (dus zou het cool moeten zijn).

Beleid van dezelfde oorsprong

Om veiligheidsredenen beperken browsers cross-origin HTTP-verzoeken geïnitieerd vanuit scripts.
XMLHttpRequesten Fetchvolgen bijvoorbeeld het same-origin-beleid.
Een webtoepassing die XMLHttpRequestof Fetchgebruikt, kan dus alleen HTTP-verzoekendoen naar zijn eigen domein.

Cross-Origin Resource Sharing (CORS)

Om webapplicaties te verbeteren, hebben ontwikkelaars browserleveranciers gevraagd om aanvragen voor meerdere domeinen toe te staan.

Het Cross-Origin Resource Sharing (CORS)mechanisme geeft webservers cross-domain access control, die veilige cross-domain data transfers mogelijk maken.
Moderne browsers gebruiken CORSin een API-container– zoals XMLHttpRequestof Fetch– om de risico’s van cross-origin te verkleinen HTTP-verzoeken.

Hoe CORS werkt (Access-Control-Allow-Originheader)

Wikipedia:

De CORS-standaard beschrijft nieuwe HTTP-headers die browsers en servers een manier bieden om externe URL’s alleen op te vragen als ze toestemming hebben.

Hoewel enige validatie en autorisatie door de server kan worden uitgevoerd, het is over het algemeen de verantwoordelijkheid van de browserom deze headers te ondersteunen en de beperkingen die ze opleggen te respecteren.

Voorbeeld

  1. De browser verzendt het OPTIONS-verzoek met een Origin HTTP-header.

    De waarde van deze header is het domein dat de bovenliggende pagina bediende. Wanneer een pagina van http://www.example.comprobeert toegang te krijgen tot de gegevens van een gebruiker in service.example.com, wordt de volgende verzoekheader verzonden naar service.example.com:

    Herkomst: http://www.example.com

  2. De server op service.example.comkan reageren met:

    • Een Access-Control-Allow-Origin(ACAO)-header in de reactie die aangeeft welke oorspronkelijke sites zijn toegestaan.
      Bijvoorbeeld:

      Access-Control-Allow-Origin: http://www.example.com

    • Een foutpagina als de server het cross-origin-verzoek niet toestaat

    • Een Access-Control-Allow-Origin(ACAO) header met een wildcard die alle domeinen toestaat:

      Access-Control-Allow-Origin: *


Antwoord 4, autoriteit 2%

Telkens wanneer ik aan CORS begin te denken, is mijn intuïtie over welke site de headers host, onjuist, zoals u in uw vraag hebt beschreven. Voor mij helpt het om na te denken over het doel van hetzelfde oorsprongsbeleid.

Het doel van hetzelfde oorsprongsbeleid is om u te beschermen tegen kwaadaardig JavaScript op siteA.com die toegang heeft tot privégegevens die u alleen met siteB.com wilt delen. Zonder hetzelfde oorsprongsbeleid kan JavaScript, geschreven door de auteurs van siteA.com, ervoor zorgen dat uw browser verzoeken doet aan siteB.com, met behulp van uw authenticatiecookies voor siteB.com. Op deze manier kan siteA.com de geheime informatie stelen die u deelt met siteB.com.

Soms moet je domeinoverschrijdend werken, en daar komt CORS om de hoek kijken. CORS versoepelt hetzelfde oorsprongsbeleid voor domainB.com, door de Access-Control-Allow-Origin-header te gebruiken om andere domeinen weer te geven (domainA.com) die worden vertrouwd om JavaScript uit te voeren dat kan communiceren met domainA.com.

Overweeg dit om te begrijpen welk domein de CORS-headers moet dienen. U bezoekt kwaadaardige.com, dat JavaScript bevat dat probeert een domeinoverschrijdend verzoek in te dienen bij mybank.com. Het zou aan mybank.com moeten zijn, niet aan kwaadaardige.com, om te beslissen of het CORS-headers instelt die hetzelfde oorsprongsbeleid versoepelen, waardoor JavaScript van kwaadaardige.com ermee kan communiceren. Als malicous.com zijn eigen CORS-headers zou kunnen instellen die zijn eigen JavaScript-toegang tot mybank.com toestaan, zou dit hetzelfde oorsprongsbeleid volledig teniet doen.

Ik denk dat de reden voor mijn slechte intuïtie het standpunt is dat ik heb bij het ontwikkelen van een site. Het is mijnsite, met al mijnJavaScript, daarom doet het niets kwaadaardigs en het zou aan mijmoeten zijn om aan te geven welke andere sites mijnJavaScript kan communiceren met. Terwijl ik eigenlijk zou moeten bedenken welke anderesites JavaScript proberen te communiceren met mijn site en moet ik CORS gebruiken om ze toe te staan?


Antwoord 5

1. Een klant downloadt javascript-code MyCode.js van http://siteA– de oorsprong.

De code die het downloaden doet – je html-scripttag of xhr van javascript of wat dan ook – kwam van, laten we zeggen, http://siteZ. En wanneer de browser MyCode.js opvraagt, stuurt het een Origin:-header met de tekst “Origin: http://siteZ“, omdat het kan zien dat u een aanvraag doet voor siteA en siteZ != siteA. (Je kunt dit niet stoppen of ermee bemoeien.)

2. De responsheader van MyCode.js bevat Access-Control-Allow-Origin: http://siteB, waarvan ik dacht dat MyCode. js mocht cross-origin verwijzingen maken naar site B.

nee. Het betekent dat alleen siteB dit verzoek mag doen. Dus uw verzoek om MyCode.js van siteZ krijgt in plaats daarvan een foutmelding en de browser geeft u meestal niets. Maar als u ervoor zorgt dat uw server in plaats daarvan A-C-A-O: siteZ retourneert, krijgt u MyCode.js . Of als het ‘*’ verzendt, dat zal werken, dat zal iedereen binnenlaten. Of als de server altijd de string verzendt vanuit de Origin: header… maar… voor de veiligheid, als je bang bent voor hackers , zou uw server alleen origins op een shortlist moeten toestaan die deze verzoeken mogen doen.

Dan komt MyCode.js van siteA. Wanneer het verzoeken doet aan siteB, zijn ze allemaal cross-origin, verzendt de browser Origin: siteA, en siteB moet siteA nemen, herkennen dat het op de korte lijst van toegestane aanvragers staat en A-C-A-O: siteA terugsturen. Alleen dan zal de browser uw script het resultaat van die verzoeken laten krijgen.


Antwoord 6

Gebruik Reacten Axios, voeg een proxylink toe aan de URL en voeg een header toe zoals hieronder weergegeven

https://cors-anywhere.herokuapp.com/+ Your API URL

Alleen door de Proxy-link toe te voegen, zal het werken, maar het kan ook opnieuw een foutmelding geven voor Geen toegang. Daarom is het beter om een header toe te voegen zoals hieronder weergegeven.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

WAARSCHUWING: niet gebruiken in productie

Dit is slechts een snelle oplossing. Als u worstelt met de reden waarom u geen antwoord kunt krijgen, KUNT u dit gebruiken.
Maar nogmaals, het is niet het beste antwoord voor productie.

Ik heb verschillende minpunten gekregen en het is volkomen logisch, ik had de waarschuwing al lang geleden moeten toevoegen.


Antwoord 7

Als u alleen een domeinoverschrijdende toepassing wilt testen waarin de browser uw verzoek blokkeert, dan kunt u uw browser gewoon in de onveilige modus openen en uw toepassing testen zonder uw code te wijzigen en zonder uw code onveilig te maken.
Vanuit MAC OS kunt u dit doen vanaf de terminalregel:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

Antwoord 8

Als je PHP gebruikt, probeer dan de volgende code toe te voegen aan het begin van het php-bestand:

Als je localhost gebruikt, probeer dan dit:

header("Access-Control-Allow-Origin: *");

Als je externe domeinen gebruikt, zoals een server, probeer dan dit:

header("Access-Control-Allow-Origin: http://www.website.com");

Antwoord 9

Vanuit mijn eigen ervaring is het moeilijk om een eenvoudige verklaring te vinden waarom CORS zelfs maar een punt van zorg is.

Zodra je begrijpt waarom het er is, worden de koppen en discussie een stuk duidelijker. Ik zal het in een paar regels proberen.


Het draait allemaal om cookies. Cookies worden door hun domein bij een klant opgeslagen.

Een voorbeeldverhaal: op uw computer staat een cookie voor yourbank.com. Misschien zit je sessie erin.

Belangrijk punt:wanneer een client een verzoek doet aan de server, verzendt deze de cookies die zijn opgeslagen onder het domein voor dat verzoek.

U bent ingelogd in uw browser op yourbank.com. U vraagt om al uw rekeningen te zien en er worden cookies verzonden voor yourbank.com. yourbank.comontvangt de stapel cookies en stuurt het antwoord terug (uw rekeningen).

Als een andere client een cross origin-verzoek doet aan een server, worden die cookies meegestuurd, net als voorheen. Ruh roh.

Je bladert naar malicious.com. Malicious doet een groot aantal verzoeken aan verschillende banken, waaronder yourbank.com.

Aangezien de cookies zijn gevalideerd zoals verwacht, autoriseert de server het antwoord.

Die cookies worden verzameld en verzonden – en nu heeft malicious.comeen reactie van yourbank.

Ja maar.


Dus nu worden een paar vragen en antwoorden duidelijk:

  • “Waarom blokkeren we de browser niet gewoon om dat te doen?” Ja. CORS.
  • “Hoe komen we er omheen?” Laat de server het verzoek vertellen dat CORS in orde is.

Antwoord 10

ik werk met express 4 en node 7.4 en hoekig, ik had hetzelfde probleem, ik help dit:
a) serverzijde: in bestand app.js geef ik headers voor alle reacties zoals:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

dit moet vóór alle routers.
Ik zag veel van deze headers toegevoegd:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

maar dat heb ik niet nodig,
b) client side: in send ajax moet je toevoegen: “withCredentials: true”, zoals:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

veel succes.


Antwoord 11

In Python gebruik ik de Flask-CORSbibliotheekmet groot succes. Het maakt het omgaan met CORS supergemakkelijk en pijnloos. Ik heb hieronder wat code uit de documentatie van de bibliotheek toegevoegd.

Installeren:

$ pip install -U flask-cors

Eenvoudig voorbeeld dat CORS toestaat voor alle domeinen op alle routes:

from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Zie de documentatie voor meer specifieke voorbeelden. Ik heb het eenvoudige voorbeeld hierboven gebruikt om het CORS-probleem te omzeilen in een ionische toepassing die ik aan het bouwen ben en die toegang moet hebben tot een aparte kolfserver.


Antwoord 12

Voor het delen van verschillende oorsprongen, stelt u de header in: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

Node: app.use('Access-Control-Allow-Origin':'*');

Hierdoor kan inhoud worden gedeeld voor verschillende domeinen.


Antwoord 13

Plak de volgende code gewoon in uw web.config-bestand.

Merk op dat u de volgende code moet plakken onder de <system.webServer>-tag

   <httpProtocol>  
    <customHeaders>  
     <add name="Access-Control-Allow-Origin" value="*" />  
     <add name="Access-Control-Allow-Headers" value="Content-Type" />  
     <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
    </customHeaders>  
  </httpProtocol>  

Antwoord 14

De antwoordheader Access-Control-Allow-Origin geeft aan of de
reactie kan worden gedeeld met het aanvragen van code van de opgegeven oorsprong.

Header type Response       header
Forbidden header name      no

Een reactie die de browser vertelt om code van elke oorsprong toe te staan om
toegang tot een bron omvat het volgende:

Access-Control-Allow-Origin: *

Ga voor meer informatie naar hier….


Antwoord 15

Nginx en Appache

Als aanvulling op apsillers antwoordzou ik graag wiki-grafiekdie laat zien wanneer het verzoek eenvoudig is of niet (en OPTIES pre-flight-verzoek wordt verzonden of niet)

Voer hier de afbeeldingsbeschrijving in

Voor een eenvoudig verzoek (bijv. hotlinking-afbeeldingen) hoeft u uw server niet te wijzigen configuratiebestanden, maar je kunt headers toevoegen in de applicatie (gehost op de server, bijv. in php) zoals Melvin Guerrero vermeldt in zijn antwoord– maar onthoud: als je volledige cors-headers toevoegt aan je server (config) en tegelijkertijd eenvoudige cors op applicatie toestaat ( bijv. php) werkt dit helemaal niet.

En hier zijn configuraties voor twee populaire servers

  • schakel CORS op Nginxin (bestand nginx.conf)


    Antwoord 16

    Ik kan het niet configureren in de back-endserver, maar met deze extensies in browsers werkt het voor mij:

    Voor Firefox:
    Cors Everywhere

    Voor Google Chrome:
    CORS toestaan: Access-Control-Allow -Oorsprong

    Opmerking: CORS werkt voor mij met deze configuratie:

    Sta CORS-opties toe

    CORS Overal opties


    Antwoord 17

    ALLEEN TIJDELIJKE OPLOSSING voor testen:

    Wie heeft geen controle over de backend voor Options 405 Method Not Allowed.
    Tijdelijke oplossing voor de Chrome-browser.
    uitvoeren in de opdrachtregel:
    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="path_to_profile"
    Voorbeeld:
    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\Users\vital\AppData\Local\Google\Chrome\User Data\Profile 2"

Other episodes