Ele permite que o navegador emita solicitações XMLHttpRequest para servidores de origem cruzada, superando assim a limitação de que o Ajax só pode ser usado na mesma origem.
Este artigo apresenta o mecanismo interno dos CORS em detalhes.
(Descrição da foto: Tirado no Oasis Park em Al Ain, Emirados Árabes Unidos)
1. Introdução
O CORS requer suporte ao navegador e do servidor. Atualmente, todos os navegadores suportam essa função e o navegador do IE não pode ser menor que o IE10.
Todo o processo de comunicação do CORS é concluído automaticamente pelo navegador e não requer participação do usuário. Para os desenvolvedores, a comunicação da CORS não é diferente da mesma comunicação de origem e o código é exatamente o mesmo. Depois que o navegador descobrir que o Ajax solicita a origem cruzada, ele adicionará automaticamente algumas informações adicionais do cabeçalho e, às vezes, haverá uma solicitação adicional, mas o usuário não sentirá.
Portanto, a chave para a implementação da comunicação CORS é o servidor. Desde que o servidor implemente a interface do CORS, a comunicação cruzada pode ser realizada.
Dois pedidos
O navegador divide solicitações de CORS em duas categorias: solicitação simples e solicitação não tão simples.
Enquanto as duas condições principais a seguir forem atendidas ao mesmo tempo, é uma solicitação simples.
(1) O método de solicitação é um dos três métodos a seguir:
HeadgetPost
(2) As informações do cabeçalho do HTTP não excedem os seguintes campos:
AceptAccept-LanguageContent-Languagelast-Event-Idcontent-Type: Limitado apenas a três valores application/x-www-form-urlencoded multipart/form-data text/plain
Qualquer pessoa que não atenda às duas condições acima ao mesmo tempo é uma solicitação não simples.
O manuseio do navegador dessas duas solicitações é diferente.
3. Solicitação simples 3.1 Processo básico
Para solicitações simples, o navegador emite diretamente a solicitação CORS. Especificamente, adicione um campo Origin às informações do cabeçalho.
O seguinte é um exemplo. O navegador descobriu que essa solicitação de origem cruzada era uma solicitação simples e adicionou automaticamente um campo Origin às informações do cabeçalho.
GET /cors HTTP/1.1Origin: http://api.bob.comHost: api.alice.comAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...
Nas informações do cabeçalho acima, Origin é usado para indicar de qual fonte (protocolo + nome de domínio + porta) a solicitação vem. Com base nesse valor, o servidor decide se deve concordar com a solicitação.
Se a fonte especificada por Origin não estiver dentro do escopo da permissão, o servidor retornará uma resposta HTTP normal. O navegador constatou que as informações do cabeçalho dessa resposta não continham o campo de Access-Control-Allow-Origin (veja abaixo para obter detalhes), por isso se sabia que ocorreu um erro e, portanto, foi lançado um erro, que foi capturado onerror função de chamada do XMLHttpRequest . Observe que esse erro não pode ser identificado pelo código de status, porque o código de status da resposta HTTP pode ser 200.
Se o nome de domínio especificado por Origin estiver dentro do escopo da permissão, a resposta retornada pelo servidor terá vários campos de cabeçalho adicionais.
Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: FooBarContent-Type: text/html; charset=utf-8
Entre as informações do cabeçalho acima, existem três campos relacionados às solicitações do CORS, todas começando com Access-Control- .
(1) Acesso-Control-Arl-Origin
Este campo é obrigatório. Seu valor é o valor do campo Origin no momento da solicitação, ou A * , indicando que a solicitação de qualquer nome de domínio é aceita.
(2) Access-Control-Arn-Credenciais
Este campo é opcional. Seu valor é um valor booleano indicando se deve permitir o envio de cookies. Por padrão, os cookies não estão incluídos nas solicitações do CORS. Defina como true , o que significa que o servidor permite explicitamente. Os cookies podem ser incluídos na solicitação e enviados ao servidor juntos. Este valor só pode ser definido como true . Se o servidor não enviar cookies pelo navegador, exclua o campo.
(3) Cabeçalhos de exposição ao controle de acesso
Este campo é opcional. Quando o CORS solicita, getResponseHeader() do objeto XMLHttpRequest pode obter apenas 6 campos básicos: Cache-Control , Content-Language , Content-Type , Expires , Last-Modified , Pragma . Se você deseja obter outros campos, deve especificá-los nos Access-Control-Expose-Headers . O exemplo acima especifica que getResponseHeader('FooBar') pode retornar o valor do campo FooBar .
3.2 Atributo Withcredentials
Como mencionado acima, as solicitações do CORS não enviam cookies e informações de autenticação HTTP por padrão. Se você deseja enviar cookies para o servidor, por um lado, precisará do servidor para concordar e especificar o campo Access-Control-Allow-Credentials .
Access-Control-Allow-Credentials: true Por outro lado, o desenvolvedor deve abrir a propriedade withCredentials na solicitação do Ajax.
var xhr = new XMLHttpRequest();xhr.withCredentials = true;Caso contrário, o navegador não enviará, mesmo que o servidor concorde em enviar cookies. Como alternativa, o servidor exige que os cookies sejam definidos e o navegador não o lidará.
No entanto, se a configuração withCredentials for omitida, alguns navegadores ainda enviarão cookies juntos. Neste momento, você pode fechar explicitamente withCredentials .
xhr.withCredentials = false; Deve-se notar que, se você deseja enviar cookies, Access-Control-Allow-Origin não pode ser definida como um asterisco e você deve especificar um nome de domínio explícito que seja consistente com a página da Web solicitada. Ao mesmo tempo, os cookies ainda seguem a política da mesma origem. Somente cookies definidos com nomes de domínio do servidor serão carregados. Os cookies de outros nomes de domínio não serão carregados e o código da página da Web document.cookie no original (original cruzado) não pode ler cookies no nome do domínio do servidor.
4. Solicitação não simples 4.1 Solicitação de pré-voo
Uma solicitação não simples é uma solicitação que possui requisitos especiais para o servidor, como o método de solicitação, é PUT ou DELETE , ou Content-Type é application/json .
Uma solicitação CORS que não é uma solicitação simples adicionará uma solicitação de consulta HTTP antes da comunicação oficial, que é chamada de solicitação de "pré -voo".
O navegador pergunta primeiro ao servidor se o nome de domínio no qual a página da web atual está localizada está na lista de licenças do servidor e quais verbos HTTP e campos de cabeçalho podem ser usados. Somente quando uma resposta positiva for recebida será o navegador será uma solicitação formal XMLHttpRequest , caso contrário, será relatado um erro.
Abaixo está um script JavaScript do navegador.
var url = 'http://api.alice.com/cors';var xhr = new XMLHttpRequest();xhr.open('PUT', url, true);xhr.setRequestHeader('X-Custom-Header', 'value');xhr.send();
No código acima, o método de solicitação HTTP é PUT e envia um cabeçalho de cabeçalho personalizado X-Custom-Header .
O navegador constatou que essa era uma solicitação não simples, por isso emitiu automaticamente uma solicitação de "pré-voo", exigindo que o servidor confirme que isso pode ser solicitado. Abaixo está as informações do cabeçalho HTTP para esta solicitação de "pré -voo".
OPTIONS /cors HTTP/1.1Origin: http://api.bob.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: X-Custom-HeaderHost: api.alice.comAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0... O método de solicitação usado pela solicitação "pré -voo" são OPTIONS , indicando que essa solicitação é usada para perguntar. Nas informações do cabeçalho, o campo principal é Origin , indicando de qual fonte a solicitação vem.
Além do campo Origin , as informações do cabeçalho da solicitação de "pré -voo" incluem dois campos especiais.
(1) Access-Control-Request-Method
Este campo é necessário para listar quais métodos HTTP serão usados para a solicitação CORS do navegador. O exemplo acima é PUT .
(2) Access-Control-Request-Headers
Este campo é uma sequência separada por vírgula que especifica o campo de informações de cabeçalho adicional que a solicitação do Browser CORS enviará. O exemplo acima é X-Custom-Header .
4.2 Resposta a solicitações de pré-voo
Depois que o servidor recebe a solicitação "pré-voo", depois de verificar Origin , Access-Control-Request-Method e Access-Control-Request-Headers , confirme que são permitidas solicitações de origem cruzada e você pode responder.
HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:15:39 GMTServer: Apache/2.0.61 (Unix)Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderContent-Type: text/html; charset=utf-8Content-Encoding: gzipContent-Length: 0Keep-Alive: timeout=2, max=100Connection: Keep-AliveContent-Type: text/plain
Na resposta HTTP acima, a chave é o campo Access-Control-Allow-Origin , o que significa que http://api.bob.com pode solicitar dados. Este campo também pode ser definido como um asterisco para concordar com qualquer solicitação de origem cruzada.
Access-Control-Allow-Origin: *
Se o navegador negar a solicitação de "pré-voo", uma resposta HTTP normal será retornada, mas não há campos de cabeçalho relacionados ao CORS. No momento, o navegador determinará que o servidor não concorda com a solicitação de pré -voo; portanto, um erro é acionado e capturado pela função de retorno de chamada onerror XMLHttpRequest . O console imprimirá a seguinte mensagem de erro.
XMLHttpRequest cannot load http://api.alice.com.Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
Outros campos relacionados aos CORS aos quais o servidor responde são os seguintes.
Access-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderAccess-Control-Allow-Credentials: trueAccess-Control-Max-Age: 1728000(1) Métodos de acesso ao controle de acesso
Esse campo é necessário e seu valor é uma sequência separada por vírgula, indicando todos os métodos de solicitação de domínio cruzado suportados pelo servidor. Observe que todos os métodos suportados são retornados, não apenas os solicitados pelo navegador. Isso é para evitar várias solicitações de "pré -voo".
(2) Cabeçalhos de acesso ao controle de acesso
Se a solicitação do navegador incluir Access-Control-Request-Headers , Access-Control-Allow-Headers será necessário. É também uma string separada por vírgula, indicando que todos os campos de cabeçalho suportados pelo servidor não estão limitados aos campos solicitados pelo navegador em "pré-voo".
(3) Access-Control-Arn-Credenciais
Este campo tem o mesmo significado que é quando solicitado de uma maneira simples.
(4) Acesso-Control-Max-Iage
Este campo é opcional e é usado para especificar o período de validade desta solicitação de pré -voo, em segundos. Nos resultados acima, o período de validade é de 20 dias (1728.000 segundos), o que significa que a resposta é armazenada em cache por 1728.000 segundos (ou seja, 20 dias). Durante esse período, nenhuma outra solicitação de pré -voo é necessária.
4.3 solicitações e respostas normais do navegador
Depois que o servidor passar a solicitação "pré -voo", toda vez que a solicitação normal do CORS do navegador é a mesma que uma solicitação simples, haverá um campo de informações do cabeçalho Origin . A resposta do servidor também terá um campo de cabeçalho Access-Control-Allow-Origin .
Abaixo está a solicitação normal do CORS do navegador após a solicitação "pré -voo".
PUT /cors HTTP/1.1Origin: http://api.bob.comHost: api.alice.comX-Custom-Header: valueAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...
O campo Origin das informações do cabeçalho acima é adicionado automaticamente pelo navegador.
Abaixo está a resposta normal do servidor.
Access-Control-Allow-Origin: http://api.bob.comContent-Type: text/html; charset=utf-8
Nas informações do cabeçalho acima, o campo Access-Control-Allow-Origin deve ser incluído em cada resposta.
5. Comparação com Jsonp
O CORS é usado na mesma finalidade que o JSONP, mas é mais poderoso que o JSONP.
O JSONP suporta apenas solicitações GET , o CORS suporta todos os tipos de solicitações HTTP. A vantagem do JSONP é que ele suporta navegadores antiquados e pode solicitar dados de sites que não suportam CORS.
(sobre)