La respuesta a la solicitud de verificación previa no pasa la verificación de control de acceso

458

Recibo este error usando ngResource para llamar a una API REST en Amazon Web Services:

XMLHttpRequest no puede cargar http://server.apiurl.com:8000/s/login?login=facebook . La respuesta a la solicitud de verificación previa no pasa la verificación de control de acceso: no hay encabezado 'Access-Control-Allow-Origin' en el recurso solicitado. Por lo tanto, el origen ' http: // localhost ' no tiene acceso permitido. Error 405

Servicio:

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

Controlador:

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

Estoy usando Chrome, y no sé qué más hacer para solucionar este problema. Incluso he configurado el servidor para aceptar encabezados de origen localhost.

Andre Mendes
fuente
confundido: ¿"configuró el servidor" o es "una API de descanso en el servicio web de Amazon"?
dandavis
3
Claramente, no ha hecho lo suficiente para habilitar CORS en el lado del servidor. Publicar muestra de encabezados de respuesta
charlietfl
44
De cualquier manera, sus votos negativos son incorrectos. Está alojando sus archivos en su máquina local. No importará qué tipo de conf él hace en la parte de atrás. Angular no permitirá este pre vuelo.
E. Maggini
3
Gracias por los comentarios, funcionó cuando configuré el navegador para desactivar la seguridad
Andre Mendes
1
Pero @Andre apagar la seguridad es sólo una solución fea donde se comprometer la seguridad, no logra resolver su problema ...
shivi

Respuestas:

241

Estás teniendo problemas con CORS.

Hay varias formas de solucionar / solucionar esto.

  1. Apaga CORS. Por ejemplo: cómo desactivar cors en cromo
  2. Use un complemento para su navegador
  3. Use un proxy como nginx. ejemplo de cómo configurar
  4. Realice la configuración necesaria para su servidor. Esto es más un factor del servidor web que ha cargado en su instancia EC2 (suponiendo que esto es lo que quiere decir con "servicio web de Amazon"). Para su servidor específico, puede consultar el sitio web enable CORS.

De manera más vergonzosa, está intentando acceder a api.serverurl.com desde localhost. Esta es la definición exacta de solicitud de dominio cruzado.

Al apagarlo solo para hacer su trabajo (OK, ponga poca seguridad para usted si visita otros sitios y simplemente tira la lata en el camino) puede usar un proxy que hace que su navegador piense que todas las solicitudes provienen del host local cuando realmente tienes un servidor local que luego llama al servidor remoto.

entonces api.serverurl.com podría convertirse en localhost: 8000 / api y su nginx local u otro proxy se enviarán al destino correcto.


Ahora por demanda popular, 100% más información CORS ... ¡el mismo gran sabor!


Y para los que votan a favor ... pasar por alto CORS es exactamente lo que se muestra para aquellos que simplemente están aprendiendo el front-end. https://codecraft.tv/courses/angular/http/http-with-promises/

E. Maggini
fuente
776
omitió lo
40
Es fácil rechazar el voto. Menos fácil arriesgarse, amigo mío. Y todo esto funciona exactamente en un entorno de desarrollo.
E. Maggini
3
En realidad funcionó. Agregué la bandera para deshabilitar la seguridad web. Para el desarrollo está bien.
Andre Mendes
15
@charlietfl ¿Cómo?
GreenAsJade
3
Gracias me salvaste el día. Solo se utilizó la primera opción: C: \ Archivos de programa (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. De: stackoverflow.com/questions/3102819/…
Harsimer
169

Mi "Servidor API" es una aplicación PHP, así que para resolver este problema encontré la siguiente solución para trabajar:

Coloque las líneas en 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');
Slipstream
fuente
3
Estoy de acuerdo, esto es mejor que la respuesta aceptada, aunque tenga cuidado al copiar estas líneas, asegúrese de modificar los métodos y el origen.
Amir Savand
11
¿Dónde ponerlo en un proyecto de Angular 6?
whatthefish
@CodyBugstein y lo que el pez pone antes de cualquier salida
Garet Claborn
Mi aplicación cliente dejó de funcionar cuando agregué un encabezado que solo requieren algunos servidores. Si la solicitud incluye encabezados personalizados, deberán aparecer en la lista Access-Control-Allow-Headers.
z0r
47

En la API web de AspNetCore, este problema se solucionó agregando "Microsoft.AspNetCore.Cors" (ver 1.1.1) y agregando los siguientes cambios en Startup.cs.

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

y

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

y poniéndose [EnableCors("AllowAllHeaders")]el controlador.

Rajkumar Peter
fuente
18
¡Esta es una buena respuesta si desea crear vulnerabilidades de secuencias de comandos en sitios cruzados! ¡Por favor, nunca hagas esto! Especifique sus dominios a los que puede acceder para evitar problemas de seguridad. CORS está ahí por una razón.
paqogomez
2
Solo para aclararlo @paqogomez, en su método ConfigureServices: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); y en su método de configuración: app.UseCors ("AllowSpecificOrigin");
Francisco Tena
28

Hay algunas advertencias cuando se trata de CORS. Primero, no permite comodines, *pero no me detenga en este, lo he leído en alguna parte y no puedo encontrar el artículo ahora.

Si realiza solicitudes desde un dominio diferente, debe agregar los encabezados de origen permitidos.

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

Si va a realizar peticiones que afectan a los recursos del servidor como de POST / PUT / PATCH, y si el tipo MIME es diferente del siguiente application/x-www-form-urlencoded, multipart/form-datao text/plainel navegador automáticamente hará una OPCIONES prevuelos solicitan comprobar con el servidor si lo permitiría .

Por lo tanto, su API / servidor debe manejar estas solicitudes de OPCIONES en consecuencia, debe responder con el apropiado access control headersy el código de estado de respuesta http debe ser 200.

Los encabezados deben ser algo como esto, ajústelos según sus necesidades:

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

El encabezado max-age es importante, en mi caso, no funcionaría sin él, supongo que el navegador necesita la información durante cuánto tiempo son válidos los "derechos de acceso".

Además, si está haciendo, por ejemplo, una POSTsolicitud con application/jsonmime desde un dominio diferente, también debe agregar el encabezado de origen de permiso mencionado anteriormente, para que se vea así:

   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

Cuando el pre-vuelo tenga éxito y obtenga toda la información necesaria, se realizará su solicitud real.

En términos generales, cualquier Access-Controlencabezado que se solicite en la solicitud inicial o previa al vuelo, se debe dar en la respuesta para que funcione.

Hay un buen ejemplo en los documentos de MDN aquí en este enlace , y también debe consultar esta publicación SO

Sasa Blagojevic
fuente
1
Aquí está el artículo de Mozilla que habla sobre cómo no se puede usar comodín para el origen de los cors: Enlace Entonces, aparentemente, esto solo se aplica cuando se usan credenciales (si lo entiendo correctamente)
Helzgate
Estoy usando comodines y envío un token de portador para autorizar la solicitud y está funcionando bien, así que no estoy seguro de a qué se refiere el enlace que proporcioné anteriormente con respecto a las credenciales. Mi problema fue que cuando agregué mi política CORS en .Net Core no agregué .AllowCredentials(). Después de agregar .AllowCredentials()todo funcionó.
Helzgate
15

JavaScript XMLHttpRequest y Fetch siguen la política del mismo origen. Por lo tanto, una aplicación web que utiliza XMLHttpRequest o Fetch solo puede realizar solicitudes HTTP a su propio dominio.

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

Debe enviar el encabezado HTTP Access-Control-Allow-Origin: * desde el lado del servidor.

Si está utilizando Apache como su servidor HTTP, puede agregarlo a su archivo de configuración de Apache de esta manera:

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

Mod_headers está habilitado de forma predeterminada en Apache, sin embargo, es posible que desee asegurarse de que esté habilitado ejecutando:

 a2enmod headers
Tadej
fuente
¿Dónde puedo encontrar mi archivo de configuración de Apache?
Shubham Arya
@ShubhamArya en Linux Debian la ubicación predeterminada es:/etc/apache2/apache2.conf
Tadej
¿Dónde puedo encontrarlo en Windows?
Shubham Arya
10

Si estás escribiendo una extensión de Chrome

Debe agregar manifest.jsonlos permisos para sus dominios.

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
freedev
fuente
1
También verifique si tiene el prefijo www
Vlas Bashynskyi
8

Si está utilizando el servidor IIS por casualidad. puede establecer debajo de los encabezados en la opción de encabezados de solicitud HTTP.

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

con esto todo post, get etc., funcionará bien.

Sunil Kumar
fuente
5

En PHP puedes agregar los encabezados:

<?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: *");
...
atiruz
fuente
gracias, funciono para mi! en pruebas y entorno de producción. Incluso usando https: //
Jose Seie
1
@atiruz Gracias por la solución. Esto funciona cuando agregué la líneaheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD
5

Para solucionar problemas de solicitudes de origen cruzado en una aplicación Node JS:

npm i cors

Y simplemente agregue las líneas de abajo a la app.js

let cors = require('cors')
app.use(cors())
Rohit Parte
fuente
3
esto sólo funciona en aplicaciones expresas js, no todas las aplicaciones de nodo
DrCord
3

En mi archivo de configuración de Apache VirtualHost, he agregado las siguientes líneas:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
abrazos
fuente
3

Para aquellos que usan Lambda Integrated Proxy con API Gateway . Debe configurar su función lambda como si estuviera enviando sus solicitudes directamente, lo que significa que la función debe configurar los encabezados de respuesta correctamente. (Si está utilizando funciones lambda personalizadas, esto será manejado por API Gateway).

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
fuente
1
También quiero intervenir y mencionar un gran problema que no creo que los documentos de AWS. Supongamos que usa la puerta de enlace API para representar su función lambda, y usa alguna API en esa función lambda. Si esa API devuelve un código de éxito de éxito no 200 y no agregó el código de éxito no 200 en la respuesta del método en la puerta de enlace API , recibirá un error y no verá su respuesta exitosa . Ejemplos de esto: Sendgrid y Twilio tienen códigos de éxito no 200.
Stephen Tetreault el
3

Creo que deshabilitar CORS de Chrome no es una buena manera , porque si lo está utilizando en iónico, ciertamente en Mobile Build, el problema volverá a surgir.

Así que mejor arreglarlo en tu backend.

En primer lugar, en el encabezado, debe establecer

  • encabezado ('Access-Control-Allow-Origin: *');
  • header ('Conjunto de encabezado Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

Y si la API se comporta como GET y POST, ambos también se configuran en el encabezado:

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header ("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) encabezado ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); salida (0); }

Shubham Pandey
fuente
3

Una causa muy común de este error podría ser que la API del host había asignado la solicitud a un método http (por ejemplo, PUT) y el cliente API está llamando a la API utilizando un método http diferente (por ejemplo, POST o GET)

Christian Nwafor
fuente
Estaba implementando CORS correctamente en mi servidor pero olvidé agregar el PUTmétodo
fguillen
3

Nuestro equipo ocasionalmente ve esto usando Vue, axios y un C # WebApi. Agregar un atributo de ruta en el punto final que está tratando de alcanzar nos lo arregla.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
fuente
No estamos realmente seguros de por qué. Jajaja Si alguien me lo hace saber!
w00ngy
1

Me he enfrentado a este problema cuando el servidor DNS se configuró en 8.8.8.8 (google's). En realidad, el problema estaba en el enrutador, mi aplicación intentó conectarse con el servidor a través de google, no localmente (para mi caso particular). He eliminado 8.8.8.8 y esto resolvió el problema. Sé que estos problemas se resolvieron mediante la configuración de CORS, pero tal vez alguien tenga el mismo problema que yo

Kirill Gusyatin
fuente
1

Estoy usando AWS sdk para cargas, después de pasar un tiempo buscando en línea me topé con este hilo. gracias a @lsimoneau 45581857 resulta que exactamente lo mismo estaba sucediendo. Simplemente apunté mi URL de solicitud a la región en mi cubo adjuntando la opción de región y funcionó.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
fuente
0

Las distribuciones independientes de GeoServer incluyen el servidor de aplicaciones Jetty. Habilite el uso compartido de recursos de origen cruzado (CORS) para permitir que las aplicaciones de JavaScript fuera de su propio dominio utilicen GeoServer.

Descomente lo siguiente <filter>y <filter-mapping>de webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Yassine Ech-Charafi
fuente
Eso no agregó antyhing al encabezado de respuesta, por lo que no funcionó
JollyRoger
1
no usa GeoServer, pero este clip me ayudó a conocer la configuración que debería usar en la aplicación que recibe la llamada.
Matt Felzani
0

Es fácil resolver este problema con solo unos pocos pasos fácilmente, sin preocuparse por nada. Amablemente, siga los pasos para resolverlo.

  1. abierto ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. vaya a la instalación y copie el comando npm install cors para instalar a través del terminal de nodo
  3. vaya a Uso simple (Habilitar todas las solicitudes CORS) desplazándose. a continuación, copie y pegue la declaración completa en su proyecto y ejecútelo ... eso funcionará con seguridad ... copie el código de comentario y péguelo en su app.js o en cualquier otro proyecte y pruebe ... esto funcionará. Esto desbloqueará cada recurso compartido de origen cruzado ... para que podamos cambiar entre los servicios para su uso
Rahul sah
fuente
1
var express = require ('express') var cors = require ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', function (req, res, siguiente) {res.json ({mensaje: '¡Esto está habilitado para CORS para todos los orígenes!'})}) app.listen (80, function () {console.log ('Servidor web habilitado para CORS que escucha en el puerto 80' )})
Rahul sah
-1

Algo que es muy fácil pasar por alto ...

En el explorador de soluciones, haga clic con el botón derecho en api-project. En la ventana de propiedades, configure 'Autenticación anónima' en Activado.

Wes
fuente
-8

Deshabilite la seguridad de Chrome. Cree un acceso directo de Chrome, haga clic con el botón derecho -> propiedades -> destino, pegue este "C: \ Archivos de programa (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user -data-dir = "c: / chromedev"

Nithin
fuente