Pyydetyssä resurssissa ei ole 'Access-Control-Allow-Origin' -otsikkoa, kun yritetään saada tietoja REST API:sta.

Yritän hakea tietoja HP Almin REST API:sta. Se toimii melko hyvin pienellä curl-skriptillä - saan tietoni.

Nyt JavaScriptin, fetchin ja ES6:n (enemmän tai vähemmän) käyttö näyttää olevan suurempi ongelma. Saan jatkuvasti tämän virheilmoituksen:

Fetch API cannot load . Vastaus esivalmistelupyyntöön ei't. läpäise pääsynvalvontatarkastusta: Ei 'Access-Control-Allow-Origin' -otsikkoa on ei ole pyydetyssä resurssissa. Origin 'http://127.0.0.1:3000' on ei siis ole sallittu pääsy. Vastauksen HTTP-tilakoodi oli 501. Jos läpinäkymätön vastaus palvelee tarpeitasi, aseta pyynnön tilaksi's mode. 'no-cors' noutaaksesi resurssin, jonka CORS on poistettu käytöstä.

Ymmärtääkseni tämä johtuu siitä, että yritän noutaa kyseistä tietoa localhostista ja ratkaisun pitäisi käyttää CORSia. Nyt luulin, että olen itse asiassa tehnyt sen, mutta jotenkin se joko jättää huomiotta sen, mitä kirjoitan otsikkoon, tai ongelma on jotain muuta?

Onko kyse siis toteutuksesta? Teenkö sen väärin? En valitettavasti voi tarkistaa palvelimen lokitietoja. Olen todella vähän jumissa tässä.

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Käytän Chromea. Yritin myös käyttää tuota Chrome CORS Pluginia, mutta sitten saan toisen virheilmoituksen:

Vastauksessa olevan 'Access-Control-Allow-Origin' -otsakkeen arvo ei saa olla jokerimerkki '*' kun pyynnön'valtuustietojen tila on 'include'. Origin 'http://127.0.0.1:3000' ei siis ole sallittu. pääsy. Valtakirjojen tila pyynnöissä, jotka on käynnistetty komennolla XMLHttpRequest -pyyntöä ohjataan withCredentials -attribuutilla.

Ratkaisu

Vastaus kattaa paljon asioita, joten se on jaettu kolmeen osaan:

  • Kuinka käyttää CORS-välityspalvelinta kiertämään "No Access-Control-Allow-Origin header " -ongelmat.
  • Miten vältetään CORS-esilentäminen
  • Miten korjata "Access-Control-Allow-Origin -otsikko ei saa olla jokerimerkki " -ongelmat?

    Kuinka käyttää CORS-välityspalvelinta "Access-Control-Allow-Origin -otsikkoa ei sallita " ongelmien kiertämiseen**. Jos et hallitse palvelinta, jolle etusivun JavaScript-koodisi lähettää pyynnön, ja palvelimen vastauksen ongelma on vain tarvittavan Access-Control-Allow-Origin-otsikon puuttuminen, voit silti saada asiat toimimaan tekemällä pyynnön CORS-välityspalvelimen kautta. Näyttääksemme, miten se toimii, tässä on ensin koodia, joka ei käytä CORS-välityspalvelinta:

const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

Syy, miksi catch-lohko osuu sinne, on se, että selain estää koodia pääsemästä käsiksi vastaukseen, joka tulee takaisin https://example.com. Syy siihen on se, että vastauksesta puuttuu Access-Control-Allow-Origin-vastausotsikko. Tässä on täsmälleen sama esimerkki, mutta siihen on lisätty CORS-välityspalvelin:

const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

Huomautus: Jos https://cors-anywhere.herokuapp.com on alhaalla tai ei ole käytettävissä, kun yrität sitä, niin katso alta, miten voit ottaa käyttöön oman CORS Anywhere -palvelimesi Herokussa vain 2-3 minuutissa. Yllä oleva toinen koodinpätkä voi käyttää vastausta onnistuneesti, koska pyynnön URL-osoitteen muuttaminen muotoon https://cors-anywhere.herokuapp.com/https://example.com-by ja sen muuttaminen vain välityspalvelimen URL-osoitteen etuliitteeksi aiheuttaa sen, että pyyntö tehdään välityspalvelimen kautta, joka sitten:

  1. Välittää pyynnön osoitteeseen "https://example.com".
  2. Vastaanottaa vastauksen osoitteesta https://example.com.
  3. Lisää vastaukseen Access-Control-Allow-Origin-otsikon.
  4. Siirtää vastauksen, johon on lisätty otsikko, takaisin sitä pyytävälle frontend-koodille. Selain sallii sitten frontend-koodin käyttää vastausta, koska selain näkee vastauksen, jossa on Access-Control-Allow-Origin -vastausotsikko. Voit helposti käyttää omaa välityspalvelinta käyttäen https://github.com/Rob--W/cors-anywhere/.
    Voit myös helposti ottaa oman välityspalvelimen käyttöön Herokussa kirjaimellisesti vain 2-3 minuutissa, 5 komennolla:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

Kun olet suorittanut nuo komennot, sinulla on lopulta oma CORS Anywhere -palvelimesi, joka toimii esimerkiksi osoitteessa https://cryptic-headland-94862.herokuapp.com/. Sen sijaan, että pyyntönumerosi URL-osoitteen etuliitteeksi laitetaan https://cors-anywhere.herokuapp.com, laitetaan sen sijaan oman instanssisi URL-osoite, esim. https://cryptic-headland-94862.herokuapp.com/https://example.com. Jos siis kun yrität käyttää https://cors-anywhere.herokuapp.com -palvelinta, huomaat, että se on alhaalla (kuten joskus käy), harkitse Heroku-tilin hankkimista (jos sinulla ei vielä ole) ja käytä 2-3 minuuttia edellä esitettyjen ohjeiden tekemiseen, jotta voit ottaa oman CORS Anywhere -palvelimesi käyttöön Herokussa. Riippumatta siitä, käytätkö omaa tai https://cors-anywhere.herokuapp.com tai muuta avointa välityspalvelinta, tämä ratkaisu toimii, vaikka pyyntö olisi sellainen, joka saa selaimet tekemään CORS-esivalvontapyynnön "OPTIONS" - koska siinä tapauksessa välityspalvelin lähettää takaisin myös "Access-Control-Allow-Headers"- ja "Access-Control-Allow-Methods"-otsakkeet, joita tarvitaan esivalvonnan onnistumiseen.

Miten vältetään CORS-esivalo Kysymyksessä oleva koodi käynnistää CORS-esivalvonnan, koska se lähettää Authorization-otsikon. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests Ilman sitäkin Content-Type: application/json-otsake aiheuttaisi esivalmistuksen. Mitä "preflight" tarkoittaa: ennen kuin selain yrittää kysymyksessä olevan koodin POST-ohjelmaa, se lähettää ensin palvelimelle OPTIONS-pyynnön selvittääkseen, suostuuko palvelin vastaanottamaan cross-origin POST-ohjelmaa, joka sisältää Authorization- ja Content-Type: application/json-otsikot.

Se toimii melko hyvin pienellä curl-skriptillä - saan tietoni. Jotta voit testata curl:lla kunnolla, sinun on jäljiteltävä selaimen lähettämää esivalmistelupyyntöä OPTIONS:

curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
    -H 'Access-Control-Request-Method: POST' \
    -H 'Access-Control-Request-Headers: Content-Type, Authorization' \
    "https://the.sign_in.url"

...jossa https://the.sign_in.url on korvattu todellisella URL-osoitteellasi, joka on sign_in. Vastauksen, jonka selaimen on nähtävä tuosta OPTIONS-pyynnöstä, on sisällettävä tämän kaltaisia otsikoita:

Access-Control-Allow-Origin:  http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization

Jos OPTIONS-vastaus ei sisällä näitä otsikoita, selain pysähtyy siihen eikä edes yritä lähettää POST-pyyntöä. Lisäksi vastauksen HTTP-tilakoodin on oltava 2xx - tyypillisesti 200 tai 204. Jos se on jokin muu tilakoodi, selain pysähtyy heti. Kyseinen palvelin vastaa "OPTIONS"-pyyntöön tilakoodilla 501, mikä ilmeisesti tarkoittaa, että se yrittää osoittaa, ettei se tue "OPTIONS"-pyyntöjä. Muut palvelimet vastaavat tässä tapauksessa yleensä tilakoodilla 405 "Method not allowed". Et siis koskaan pysty tekemään POST-pyyntöjä suoraan kyseiselle palvelimelle etusivun JavaScript-koodistasi, jos palvelin vastaa OPTIONS-pyyntöön 405- tai 501-statuksella tai muulla kuin 200- tai 204-statuksella tai jos se ei vastaa tarvittavilla vastausotsikoilla. Tapa välttää preflightin käynnistäminen kysymyksessä mainitussa tapauksessa olisi seuraava:

  • jos palvelin ei vaatisi Authorization-pyyntöotsikkoa, vaan sen sijaan (esimerkiksi) luottaisi POST-pyynnön runkoon tai kyselyparametriin upotettuihin todennustietoihin.
  • jos palvelin ei edellyttäisi, että POST-rungossa olisi mediatyyppi Content-Type: application/json, vaan sen sijaan hyväksyisi POST-rungon muodossa application/x-www-form-urlencoded, jossa on parametri nimeltä json (tai mikä tahansa muu), jonka arvona on JSON-tieto.

    Miten korjata "Access-Control-Allow-Origin -otsikko ei saa olla jokerimerkki " -ongelmat**.

    Saan toisen virheilmoituksen:

    Vastauksessa olevan 'Access-Control-Allow-Origin' -otsikon arvo ei saa olla jokerimerkki '' kun pyynnön'valtuustietojen tila on 'include'. Alkuperä 'http://127.0.0.1:3000' ei siis ole sallittu. pääsy. Valtakirjojen tila pyynnöissä, jotka on käynnistetty komennolla XMLHttpRequest -pyyntöä ohjataan withCredentials -attribuutilla. Selaimet eivät anna etusivun JavaScript-koodin käyttää vastausta, jos Access-Control-Allow-Origin-vastausotsikon arvo on `. Sen sijaan arvon on tässä tapauksessa täsmälleen vastattava frontend-koodisi alkuperää,http://127.0.0.1:3000. Katso [*Credentialed requests and wildcards*][1] MDN:n HTTP:n pääsynvalvonta (CORS) -artikkelissa. Jos hallitset palvelinta, jolle lähetät pyynnön, yleinen tapa käsitellä tätä tapausta on määrittää palvelin ottamaanOrigin-pyyntöotsikon arvo ja kaiku/heijastamaan se takaisinAccess-Control-Allow-Origin`-vastausotsikon arvoon. Esimerkiksi nginxin kanssa:

add_header Access-Control-Allow-Origin $http_origin

Mutta tämä on vain yksi esimerkki; muut (verkko)palvelinjärjestelmät tarjoavat samanlaisia tapoja alkuperäarvojen kaiuttamiseen.

Käytän Chromea. Yritin myös käyttää tuota Chrome CORS Pluginia. Tuo Chrome CORS -lisäosa ilmeisesti vain yksinkertaisesti pistää Access-Control-Allow-Origin: *-otsikon selaimen näkemään vastaukseen. Jos lisäosa olisi fiksumpi, se asettaisi tuon väärennetyn Access-Control-Allow-Origin-vastausotsikon arvoksi etusivun JavaScript-koodin todellisen alkuperän, http://127.0.0.1:3000. Vältä siis kyseisen laajennuksen käyttöä edes testauksessa. Se on vain häiriötekijä. Jos haluat testata, mitä vastauksia saat palvelimelta ilman selaimen suodatusta, sinun on parempi käyttää curl -H kuten edellä.

Mitä tulee kysymyksessä esitetyn fetch(...)-pyynnön etusivun JavaScript-koodiin:

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

Poista nämä rivit. Access-Control-Allow-*-otsikot ovat vastauksen otsikoita. Et koskaan halua lähettää niitä pyynnössä. Ainoa vaikutus, joka sillä on, on se, että se käynnistää selaimen tekemään preflightin.

Kommentit (8)

Tämä virhe ilmenee, kun asiakkaan URL-osoite ja palvelimen URL-osoite eivät täsmää, porttinumero mukaan lukien. Tässä tapauksessa sinun on otettava palvelussasi käyttöön CORS eli cross origin resource sharing.

Jos isännöit Spring REST -palvelua, löydät sen blogikirjoituksesta CORS-tuki Spring Frameworkissa.

Jos isännöit palvelua Node.js-palvelimella, niin sitten

  1. Pysäytä Node.js-palvelin.

  2. npm install cors --save.

  3. Lisää seuraavat rivit server.js-tiedostoon

    var cors = require('cors')

    app.use(cors()) // Käytä tätä muuttujan ilmoittamisen jälkeen

Kommentit (4)

Poista tämä:

credentials: 'include',
Kommentit (0)