¿cómo evitar Access-Control-Allow-Origin?


Estoy haciendo una llamada ajax a mi propio servidor en una plataforma que establecen evitar estas llamadas ajax (pero lo necesito para obtener los datos de mi servidor para mostrar los datos recuperados de la base de datos de mi servidor). Mi script ajax está funcionando, puede enviar los datos al script php de mi servidor para permitirle procesarlos. Sin embargo, no puede recuperar los datos procesados, ya que está bloqueado por "Access-Control-Allow-Origin"

No tengo acceso al origen/núcleo de esa plataforma. así que no puedo eliminar el script que no me permite hacer tan. (P/S Utilicé la consola de Google Chrome y descubrí este error)

El código Ajax como se muestra a continuación:

 $.ajax({
     type: "GET",
     url: "http://example.com/retrieve.php",
     data: "id=" + id + "&url=" + url,
     dataType: 'json',   
     cache: false,
     success: function(data)
      {
        var friend = data[1];              
        var blog = data[2];           
        $('#user').html("<b>Friends: </b>"+friend+"<b><br> Blogs: </b>"+blog);

      } 
  });

O hay un código JSON equivalente al script ajax anterior ? Creo que JSON está permitido.

Espero que alguien pueda ayudarme.

Author: Ram Patra, 2011-09-27

8 answers

Ponlo encima de retrieve.php

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

Es importante tener en cuenta que el header() debe ser llamado antes de que se envíe cualquier salida real.

Incorrecto

<html>
<?php
header('Access-Control-Allow-Origin: *'); 
?>

Correcto

<?php
header('Access-Control-Allow-Origin: *'); 
?>
<html>
 326
Author: Rafay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 17:48:29

Está bien, pero todos ustedes saben que el * es un comodín y permite cross site scripting desde todos los dominios?

Le gustaría enviar múltiples Access-Control-Allow-Origin encabezados para cada sitio que está permitido - pero desafortunadamente oficialmente no es compatible para enviar múltiples Access-Control-Allow-Origin encabezados, o para poner en múltiples orígenes.

Puede resolver esto comprobando el origen y enviándolo de vuelta en el encabezado, si está permitido:

$origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = [
    'http://mysite1.com',
    'https://www.mysite2.com',
    'http://www.mysite2.com',
];

if (in_array($origin, $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $origin);
}

Eso es mucho más seguro. Es posible que desee editar la coincidencia y cámbialo a una función manual con alguna expresión regular, o algo así. Al menos esto solo enviará de vuelta 1 encabezado, y usted estará seguro de que es el que la solicitud vino de. Tenga en cuenta que todos los encabezados HTTP pueden ser falsificados, pero este encabezado es para la protección del cliente. No proteja sus propios datos con esos valores. Si quieres saber más, lee un poco sobre CORS y CSRF.

¿por Qué es más seguro?

Permitiendo el acceso desde otras ubicaciones y luego desde las tuyas sitio de confianza permite highjacking sesión. Facebook Facebook permite un origen comodín - esto significa que usted puede hacer su propio sitio web en algún lugar, y hacer que el fuego llamadas AJAX (o abrir iframes) a facebook. Esto significa que puede obtener la información de inicio de sesión del facebook de un visitante de su sitio web. Peor aún: puedes escribir POST solicitudes y publicar datos en el facebook de alguien, solo mientras están navegando por tu sitio web.

Tenga mucho cuidado al usar el ACAO encabezados!

 251
Author: Rob Quist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-01 09:59:59

Advertencia , Chrome (y otros navegadores) se quejará de que se establecen múltiples encabezados ACAO si sigue algunas de las otras respuestas.

El error será algo como XMLHttpRequest cannot load ____. The 'Access-Control-Allow-Origin' header contains multiple values '____, ____, ____', but only one is allowed. Origin '____' is therefore not allowed access.

Prueba esto:

$http_origin = $_SERVER['HTTP_ORIGIN'];

$allowed_domains = array(
  'http://domain1.com',
  'http://domain2.com',
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}
 25
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-10 12:00:14

He solucionado este problema al llamar a un controlador MVC3. He añadido:

Response.AddHeader("Access-Control-Allow-Origin", "*"); 

Antes de mi

return Json(model, JsonRequestBehavior.AllowGet);

Y también mi $.ajax se quejaba de que no acepta cabecera Content-type en mi llamada ajax, así que lo comenté ya que sé que su JSON se pasa a la Acción.

Espero que eso ayude.

 7
Author: Atif Rehman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-19 14:14:33

Lo mejor sería permitir dominios individuales, tenga cuidado con el http://:

     header('Access-Control-Allow-Origin: http://www.foo.com', false);
     header('Access-Control-Allow-Origin: http://www.foo2.com', false));
 6
Author: Sebastian Viereck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-26 10:03:06

¿Ha intentado realmente agregar el encabezado Access-Control-Allow-Origin a la respuesta enviada desde su servidor? Como, Access-Control-Allow-Origin: *?

 3
Author: Daniel Brockman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-27 06:07:44

Es una muy mala idea usar *, lo que te deja muy abierto a cross site scripting. Básicamente, desea tener su propio dominio todo el tiempo, con el alcance de su configuración SSL actual y, opcionalmente, dominios adicionales. También desea que todos se envíen como un encabezado. Lo siguiente siempre autorizará su propio dominio en el mismo ámbito SSL que la página actual, y opcionalmente también puede incluir cualquier número de dominios adicionales. Los enviará a todos como un encabezado, y sobrescribirá el anterior uno (s) si algo más ya los envió para evitar cualquier posibilidad de que el navegador se queje sobre múltiples encabezados de control de acceso que se envían.

class CorsAccessControl
{
    private $allowed = array();

    /**
     * Always adds your own domain with the current ssl settings.
     */
    public function __construct()
    {
        // Add your own domain, with respect to the current SSL settings.
        $this->allowed[] = 'http'
            . ( ( array_key_exists( 'HTTPS', $_SERVER )
                && $_SERVER['HTTPS'] 
                && strtolower( $_SERVER['HTTPS'] ) !== 'off' ) 
                    ? 's' 
                    : null )
            . '://' . $_SERVER['HTTP_HOST'];
    }

    /**
     * Optionally add additional domains. Each is only added one time.
     */
    public function add($domain)
    {
        if ( !in_array( $domain, $this->allowed )
        {
            $this->allowed[] = $domain;
        }
    /**
     * Send 'em all as one header so no browsers grumble about it.
     */
    public function send()
    {
        $domains = implode( ', ', $this->allowed );
        header( 'Access-Control-Allow-Origin: ' . $domains, true ); // We want to send them all as one shot, so replace should be true here.
    }
}

Uso:

$cors = new CorsAccessControl();

// If you are only authorizing your own domain:
$cors->send();

// If you are authorizing multiple domains:
foreach ($domains as $domain)
{
    $cors->add($domain);
}
$cors->send();

Usted consigue la idea.

 0
Author: mopsyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-23 01:16:02

Si pruebas desde localhost también puedes usar:
header('Access-Control-Allow-Origin: http://localhost:8080', false); donde 8080 es el puerto que está probando.

 0
Author: Philip D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-15 15:57:50