A origem não é permitida pelo Access-Control-Allow-Origin

337

Estou criando um Ajax.requestservidor PHP remoto em um aplicativo Sencha Touch 2 ( incluído no PhoneGap ).

A resposta do servidor é a seguinte:

XMLHttpRequest não pode carregar http://nqatalog.negroesquisso.pt/login.php . A origem http://localhost:8888não é permitida pelo Access-Control-Allow-Origin.

Como posso resolver este problema?

Ricardo
fonte
19
enquanto estiver usando jQuery, ajuste dataType: 'jsonp',faz o truque
Amit
11
pela maneira que não é a resposta do servidor. Para ser preciso, esse erro é emitido no lado do cliente.
Matteo
2
O truque jsonp provavelmente não funciona mais, fyi: stackoverflow.com/questions/12216208/...
drewww
7
Observe que desde que perdi meio dia perseguindo esse bug - Se o script do lado do servidor falhar com um erro interno do servidor, o navegador poderá interpretá-lo como se a solicitação não fosse permitida devido Access-Control-Allow-Origine reportar isso como erro.
troelskn 02/09
11
@troelskn Você acabou de salvar minha vida. Eu estava procurando por algum erro de CORS desde 3 dias, e era simplesmente um pequeno problema de configuração do Spring causando um 500, que eu resolvi em 5 minutos depois de ler seu comentário e realmente o procurei. Obrigado!
Alexis Dufrenoy

Respostas:

378

Escrevi um artigo sobre esse assunto há algum tempo, Cross Domain AJAX .

A maneira mais fácil de lidar com isso se você tiver controle do servidor de resposta é adicionar um cabeçalho de resposta para:

Access-Control-Allow-Origin: *

Isso permitirá que o Ajax entre domínios . No PHP, você deseja modificar a resposta da seguinte maneira:

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

Você pode simplesmente colocar a Header set Access-Control-Allow-Origin *configuração na configuração do Apache ou no arquivo htaccess.

Deve-se observar que isso desativa efetivamente a proteção CORS, o que provavelmente expõe seus usuários a ataques . Se você não sabe que precisa especificamente usar um curinga, não deve usá-lo e, em vez disso, deve colocar seu domínio específico na lista de permissões:

<?php header('Access-Control-Allow-Origin: http://example.com') ?>
Matt Mombrea
fonte
4
Vou entrar em contato com meu provedor de servidores. Obrigado
Ricardo
8
Há alguma preocupação de segurança com isso? Esta resposta , por exemplo, diz "O JavaScript é limitado pela" mesma política de origem "por motivos de segurança. Por exemplo, um script malicioso não pode entrar em contato com um servidor remoto e enviar dados confidenciais do seu site".
JohnK
4
Incrível, acabei de colocar isso no meu arquivo do servidor node.js.: response.writeHead (200, {'Content-Type': contentType, 'Access-Control-Allow-Origin': '*'}); E funcionou. Obrigado!
vbullinger
25
JohnK, sim, o curinga permitirá que qualquer domínio envie solicitações ao seu host. Eu recomendo substituir o asterisco por um domínio específico no qual você executará scripts.
Nick
7
É interessante que você ache que o curinga nem deveria ser sugerido @jfrej. Tudo depende do seu objetivo. Por exemplo, o motivo pelo qual usamos o curinga (e postamos esta resposta) foi porque estávamos construindo um widget incorporado para qualquer site usar.
Matt Mombrea
63

Se você não tem o controle do servidor, você pode simplesmente adicionar este argumento para seu lançador Chrome: --disable-web-security.

Note que eu não usaria isso para "navegação na web" normal. Para referência, consulte esta postagem: Desative a mesma política de origem no Chrome .

Se você usar o Phonegap para criar o aplicativo e carregá-lo no dispositivo, isso não será um problema.

Travis Webb
fonte
Obrigado. Mas meu aplicativo está sendo executado em dispositivos móveis, não posso passar argumentos para o meu wrapper de visualização na web.
Ricardo
Você não testa seu aplicativo em um navegador primeiro? Como você depura?
Travis Webb
Sim, eu depuro em um navegador Chrome, mas o aplicativo não roda no chrome. Será no phonegap webview que eu não posso controlar.
Ricardo
4
leia a resposta: você pode simplesmente adicionar esse argumento ao seu iniciador do Chrome . Não há nenhuma configuração para isso dentro do Chrome
Travis Webb
2
Claro que é inseguro. O OP está pedindo uma maneira de contornar as medidas de segurança.
Travis Webb
42

Se você estiver usando o Apache, basta adicionar:

<ifModule mod_headers.c>
    Header set Access-Control-Allow-Origin: *
</ifModule>

na sua configuração. Isso fará com que todas as respostas do seu servidor da Web sejam acessíveis a partir de qualquer outro site na Internet. Se você pretende permitir apenas que os serviços em seu host sejam usados ​​por um servidor específico, substitua-o *pelo URL do servidor de origem:

Header set Access-Control-Allow-Origin: http://my.origin.host
Reza S
fonte
3
E não se esqueça de carregar o módulo: a2enmod cabeçalhos
Walery Strauch
como carregar module: a2enmod headers?
precisa
18

Se você tiver um aplicativo ASP.NET / ASP.NET MVC , poderá incluir esse cabeçalho através do arquivo Web.config:

<system.webServer>
  ...

    <httpProtocol>
        <customHeaders>
            <!-- Enable Cross Domain AJAX calls -->
            <remove name="Access-Control-Allow-Origin" />
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>
C. Augusto Proiete
fonte
2
Pessoal do .NET MVC, OLHE aqui! Na verdade, vou digitar uma solução e apontar para essa resposta no meu blog para que as pessoas possam encontrá-la mais fácil. Nada pior do que tentar superar um obstáculo .NET / MVC e encontrar apenas soluções PHP / jQuery. Obrigado @ Caio-Proiete
ottoflux
11
Como isso não funciona para mim? Estou usando o Chrome e tentando acessar a página de finanças do yahoo no meu host local.
New7 de
11
obrigado funcionou para mim. Eu adicionei no projeto de código do lado do servidor (web.config).
Ethem
15

Esta foi a primeira pergunta / resposta que surgiu para mim ao tentar resolver o mesmo problema usando o ASP.NET MVC como a fonte dos meus dados. Sei que isso não resolve o PHP questão , mas está relacionado o suficiente para ser valioso.

Estou usando o asp.net MVC. O post de Greg Brant funcionou para mim. Por fim, você cria um atributo, [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]que pode adicionar às ações do controlador.

Por exemplo:

public class HttpHeaderAttribute : ActionFilterAttribute
{
    public string Name { get; set; }
    public string Value { get; set; }
    public HttpHeaderAttribute(string name, string value)
    {
        Name = name;
        Value = value;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.AppendHeader(Name, Value);
        base.OnResultExecuted(filterContext);
    }
}

E depois usá-lo com:

[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
    return Json( "Some public result" );
}
badMonkey
fonte
11
O WebApi 2 incorporou isso agora. asp.net/web-api/overview/security/…
Matt Frear
10

Como Matt Mombrea está correto para o lado do servidor, você pode encontrar outro problema que é a rejeição da lista de permissões.

Você precisa configurar seu phonegap.plist. (Estou usando uma versão antiga do phonegap)

Para cordova, pode haver algumas alterações no nome e no diretório. Mas as etapas devem ser basicamente as mesmas.

Primeiro selecione Arquivos de suporte> PhoneGap.plist

insira a descrição da imagem aqui

depois em "ExternalHosts"

Adicione uma entrada, com um valor de talvez " http://nqatalog.negroesquisso.pt ". Estou usando * apenas para fins de depuração.

insira a descrição da imagem aqui

steve0hh
fonte
8

Isso pode ser útil para quem precisa de uma exceção para as versões 'www' e 'não www' de um referenciador:

 $referrer = $_SERVER['HTTP_REFERER'];
 $parts = parse_url($referrer);
 $domain = $parts['host'];

 if($domain == 'google.com')
 {
         header('Access-Control-Allow-Origin: http://google.com');
 }
 else if($domain == 'www.google.com')
 {
         header('Access-Control-Allow-Origin: http://www.google.com');
 }
lewsid
fonte
Apontou-me na direção certa para resolver o erro ACAO com o azure. Enquanto eu adicionava o nome de host permitido do googledrive. O URL usado precisa ser googledrive NÃO googledrive
Kildareflare
7

Vou lhe dar uma solução simples para este. No meu caso, não tenho acesso a um servidor. Nesse caso, você pode alterar a política de segurança no seu navegador Google Chrome para permitir acesso-controle-permissão-origem. Isto é muito simples:

  1. Crie um atalho do navegador Chrome
  2. Clique com o botão direito do mouse no ícone de atalho -> Propriedades -> Atalho -> Alvo

Colar simples "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.

A localização pode ser diferente. Agora abra o Chrome clicando nesse atalho.

Dibish
fonte
7

Eu me deparei com isso algumas vezes ao trabalhar com várias APIs. Geralmente, uma solução rápida é adicionar "& callback =?" até o final de uma string. Às vezes, o "e comercial" precisa ser um código de caractere e, às vezes, um "?": "? Callback =?" (consulte Uso da API Forecast.io com jQuery )

Francis Baptiste
fonte
6

Se você estiver escrevendo uma extensão do Chrome e obter este erro, então não se esqueça de adicionar URL base da API para o seu manifest.json's permissões bloco , exemplo:

"permissions": [
    "https://itunes.apple.com/"
]
itzg
fonte
6

Isso ocorre devido à política de mesma origem . Veja mais em Mozilla Developer Network ou Wikipedia .

Basicamente, no seu exemplo, você precisa carregar a http://nqatalog.negroesquisso.pt/login.phppágina apenas de nqatalog.negroesquisso.pt, não localhost.

antyrat
fonte
11
Mas preciso carregar o serviço da web a partir de um dispositivo móvel, eu ignoraria isso?
Ricardo
Bem, você precisa fazer algumas alterações do lado do servidor ou usar JSONP en.wikipedia.org/wiki/JSONP
antyrat
6

se você estiver no apache, basta adicionar um arquivo .htaccess ao seu diretório com este conteúdo:

Header set Access-Control-Allow-Origin: *

Header set Access-Control-Allow-Headers: content-type

Header set Access-Control-Allow-Methods: *
Vero O
fonte
5

No Ruby on Rails , você pode fazer em um controlador:

headers['Access-Control-Allow-Origin'] = '*'
fuzzyalej
fonte
em que controlador você coloca isso se for uma chamada ajax? Posso ver mais contexto de código?
rigdonmr
5

Você pode fazê-lo funcionar sem modificar o servidor, fazendo com que o navegador inclua o cabeçalho Access-Control-Allow-Origin: *nas respostas das OPÇÕES HTTP.

No Chrome, use esta extensão . Se você estiver no Mozilla, verifique esta resposta .

forzagreen
fonte
5

Se você obtiver isso no Angular.js, não se esqueça do número da porta assim:

var Project = $resource(
    'http://localhost\\:5648/api/...', {'a':'b'}, {
        update: { method: 'PUT' }
    }
);

Veja aqui para mais informações.

Marius
fonte
4

Também temos o mesmo problema com o aplicativo phonegap testado no chrome. Uma máquina Windows que usamos abaixo do arquivo em lotes todos os dias antes de abrir o Chrome. Lembre-se, antes de executar isso, você precisa limpar todas as instâncias do chrome do gerenciador de tarefas ou pode selecionar o chrome para não executar em segundo plano.

LOTE: (use cmd)

cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security
abksharma
fonte
1

Na cidade Ruby Sinatra

response['Access-Control-Allow-Origin'] = '*' 

para todos ou

response['Access-Control-Allow-Origin'] = 'http://yourdomain.name' 
Mikhail Chuprynski
fonte
0

Quando você recebe a solicitação, pode

var origin = (req.headers.origin || "*");

do que quando você tem que responder, vá com algo assim:

res.writeHead(
    206,
    {
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Origin': origin,
    }
);
Alessandro Annini
fonte