javascript - Svar på preflight-forespørsel passerer ikke tilgangskontrollsjekk - Ingen 'Access-Control-Allow-Origin'-header


Jeg får denne feilen når jeg bruker ngResource for å kalle en REST API på Amazon Web Services:

XMLHttpRequest kan ikke laste http://server.apiurl.com:8000/s/login?login=facebook. Responsen på preflight-forespørselen passerer ikke adgangskontrollsjekken: Ingen 'Access-Control-Allow-Origin'-header er til stede på den forespurte ressursen. Opprinnelsen 'http://localhost' har derfor ikke tilgang. Feil 405

Service :

socialMarkt.factory('loginService', ['$resource', function ($resource) {
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, {
        login: "facebook",
        access_token: "@access_token",
        facebook_id: "@facebook_id"
    }, {
        getUser: {
            method: 'POST'
        }
    });
}]);

Kontroller:

[...]
loginService.getUser(JSON.stringify(fbObj)),
    function (data) {
        console.log(data);
    },
    function (result) {
        console.error('Error', result.status);
    }
[...]

Jeg bruker Chrome. Hva mer kan jeg gjøre for å fikse dette problemet?

Jeg har til og med konfigurert serveren til å godta headere fra opprinnelse localhost.

Svar #1

Du støter på CORS-problemer.

Det finnes flere måter å fikse eller omgå dette på.

  1. Deaktiver CORS. For eksempel: Hvordan deaktivere CORS i Chrome
  2. Bruk en plugin for nettleseren din
  3. Bruk en proxy, for eksempel nginx. Eksempel på hvordan man setter det opp
  4. Gå gjennom nødvendig oppsett for serveren din. Dette er i større grad en faktor av webserveren du har installert på EC2-instansen din (forutsatt at dette er det du mener med «Amazon web service»). For din spesifikke server kan du se på nettstedet for å aktivere CORS.

Mer utførlig prøver du å få tilgang til api.serverurl.com fra localhost. Dette er den eksakte definisjonen på en tverrdomeneforespørsel.

Enten ved å slå det av bare for å få arbeidet ditt gjort (OK, men dårlig sikkerhet for deg hvis du besøker andre nettsteder og bare skyver problemet videre) eller du kan bruke en proxy som får nettleseren din til å tro at alle forespørsler kommer fra lokal vert når du egentlig har en lokal server som deretter kaller den eksterne serveren.

Så api.serverurl.com kan bli localhost:8000/api, og din lokale nginx eller annen proxy vil sende til riktig destinasjon.


Nå på populær forespørsel, 100 % mer CORS-informasjon—samme gode smak!


Å omgå CORS er akkurat det som vises for de som bare lærer front-end. HTTP-eksempel med løfter

Svar #2

Min "API-server" er en PHP-applikasjon, så for å løse dette problemet fant jeg følgende løsning:

Plasser disse linjene i filen index.php:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

Svar #3

I ASP.NET Core Web API ble dette problemet løst ved å legge til "Microsoft.AspNetCore.Cors" (versjon 1.1.1) og legge til følgende endringer i Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("AllowAllHeaders",
            builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyHeader()
                       .AllowAnyMethod();
            });
    });
    .
    .
    .
}

og

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

Og å sette [EnableCors("AllowAllHeaders")] i kontrolleren.

Svar #4

Det er noen forbehold når det gjelder CORS. For det første tillater det ikke jokertegn *, men ikke hold meg til dette. Jeg har lest det et sted, og jeg finner ikke artikkelen nå.

Hvis du sender forespørsler fra et annet domene, må du legge til allow origin-headere.

Access-Control-Allow-Origin: www.other.com

Hvis du sender forespørsler som påvirker serverressurser som POST/PUT/PATCH, og hvis MIME-typen er forskjellig fra følgende application/x-www-form-urlencoded, multipart/form-data eller text/plain, vil nettleseren automatisk sende en forhånds-OPTIONS-forespørsel for å sjekke med serveren om det er tillatt.

Så API-et/serveren din må håndtere disse OPTIONS-forespørslene deretter, du må svare med de riktige tilgangskontrolloverskriftene og HTTP-responsstatuskoden må være 200.

Overskriftene bør være noe sånt som dette, juster dem etter dine behov:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Max-age-headeren er viktig, i mitt tilfelle ville det ikke fungere uten den, jeg antar at nettleseren trenger informasjonen om hvor lenge "tilgangsrettighetene" er gyldige.

I tillegg, hvis du for eksempel lager en POST-forespørsel med application/json mime fra et annet domene, må du også legge til den tidligere nevnte allow origin-headeren, så det vil se slik ut:

   Access-Control-Allow-Origin: www.other.com
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Når forhåndssjekken lykkes og får all nødvendig informasjon, vil den faktiske forespørselen din bli gjort.

Generelt sett bør uansett hvilke Access-Control-overskrifter som etterspørres i den innledende eller pre-flight-forespørselen, gis i svaret for at det skal fungere.

Det er et godt eksempel i MDN-dokumentasjonen her på denne lenken, og du bør også sjekke ut dette innlegget på Stack Overflow.

Svar #5

Hvis du skriver en Chrome-utvidelse

I manifest.json-filen må du legge til tillatelsene for domenet/domenene dine.

"permissions": [
   "http://example.com/*",
   "https://example.com/*",
   "http://www.example.com/*",
   "https://www.example.com/*"
]

Svar #6

JavaScript XMLHttpRequest og Fetch følger retningslinjen om samme opprinnelse. Så en nettapplikasjon som bruker XMLHttpRequest eller Fetch kan kun gjøre HTTP-forespørsler til sitt eget domene.

Kilde: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Du må sende Access-Control-Allow-Origin: * HTTP-headeren fra serversiden din.

Hvis du bruker Apache som HTTP-server, kan du legge det til i Apache-konfigurasjonsfilen din slik:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers er aktivert som standard i Apache, men du vil kanskje sikre at det er aktivert ved å kjøre:

 a2enmod headers

Svar #7

I PHP kan du legge til overskriftene:

<?php
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Expose-Headers: Content-Length, X-JSON");
    header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
    header("Access-Control-Allow-Headers: *");
    ...

Svar #8

For å fikse problemer med forespørsler på tvers av opprinnelse i en Node.js-applikasjon:

npm i cors

Og legg ganske enkelt til linjene nedenfor i app.js-filen:

let cors = require('cors')
app.use(cors())

Svar #9

Hvis du tilfeldigvis bruker IIS-serveren, kan du sette de nedenstående headerne i alternativet for HTTP-forespørselsheadere.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

Med dette vil alle POST, GET osv. fungere fint.

Relaterte artikler