16 [Domínio cruzado]

16 [Domínio cruzado]

1. O que é domínio cruzado

Domínio cruzado significa que os navegadores não podem executar scripts de outros sites. É causado pela política de mesma origem do navegador, que é uma restrição de segurança imposta pelo navegador no JavaScript. Quando um navegador solicita recursos de outro nome de domínio de uma página da Web de um nome de domínio, qualquer diferença no nome de domínio, porta ou protocolo é considerada entre domínios.

A política de mesma origem restringe os seguintes comportamentos:

Cookies, LocalStorage e IndexDB não podem ser lidos

Objetos DOM e JS não podem ser buscados

A solicitação Ajax não pode ser enviada

Aqui está um exemplo:

http://www.yyy.cn/index.html 调用 http://www.xxxyyy.cn/server.php 非跨域

http://**www.xxxyyy.cn**/index.html 调用  http://**www.xxx.cn**/server.php  跨域,主域不同

http://**abc**.xxxyyy.cn/index.html 调用  http://**def**.xxx.cn/server.php  跨域,子域名不同

http://www.xxx.cn:**8080**/index.html 调用  http://www.xxx.cn/server.php  跨域,端口不同

**https**://www.xxx.cn/index.html 调用  **http**://www.xxx.cn/server.php  跨域,协议不同

2. CORS de compartilhamento de recursos entre origens

Esta é a solução mainstream atual.

CORS é um padrão W3C e seu nome completo é "Compartilhamento de recursos de origem cruzada". Ele permite que os navegadores enviem solicitações XMLHttpRequest para servidores de origem cruzada, superando assim a limitação de que o AJAX só pode ser usado na mesma origem.

O CORS requer suporte para navegador e servidor. Atualmente, todos os navegadores suportam esta função e o navegador IE não pode ser inferior ao IE10. IE8+: IE8/9 precisa usar o objeto XDomainRequest para suportar CORS.

Todo o processo de comunicação do CORS é concluído automaticamente pelo navegador sem a participação do usuário. Para desenvolvedores, não há diferença entre comunicação CORS e comunicação AJAX de mesma origem, e o código é exatamente o mesmo. Assim que o navegador descobrir que a solicitação AJAX é de origem cruzada, ele adicionará automaticamente algumas informações de cabeçalho adicionais e, às vezes, haverá uma solicitação adicional, mas o usuário não a sentirá. Portanto, a chave para realizar a comunicação CORS é o servidor .

Basicamente, você só precisa adulterar o servidor , e o código do front-end é o mesmo de quando é da mesma fonte, ou seja, é o mesmo quando não é cross-domain.

Este método é dividido em duas requisições:

Uma é uma solicitação simples e a outra é uma solicitação não simples. Desde que as seguintes condições sejam atendidas, é uma solicitação simples

O método de solicitação é HEAD, POST ou GET

As informações do cabeçalho http não excedem os seguintes campos:

AcceptAccept-Language 

Content-Language

Last-Event-ID

Content-Type(限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain)

Por que é dividido em solicitações simples e solicitações não simples, porque os navegadores lidam com esses dois métodos de solicitação de maneira diferente.

2.1 Pedido Simples

Para solicitações simples, o navegador faz uma solicitação CORS diretamente. Especificamente, um campo Origem é adicionado às informações do cabeçalho. Veja a seguir um exemplo: quando o navegador descobre que essa solicitação AJAX de origem cruzada é uma solicitação simples, ele adiciona automaticamente um campo Origem às informações do cabeçalho.

GET /cors HTTP/1.1

Origin: http://api.bob.com

Host: api.alice.com

Accept-Language: en-US

Connection: keep-alive

User-Agent: Mozilla/5.0

...

O campo Origem é usado para indicar de qual fonte (protocolo + nome de domínio + porta) esta solicitação vem. Com base nesse valor, o servidor decide se concorda com a solicitação.

Se a origem especificada por Origin não estiver dentro do intervalo permitido, o servidor retornará uma resposta HTTP normal. Quando o navegador descobre que as informações do cabeçalho de resposta não contêm o campo Access-Control-Allow-Origin, ele sabe que algo deu errado e, portanto, lança um erro, que é capturado pela função onerror callback de XMLHttpRequest.

Observe que esse tipo de 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 pelo Origin estiver dentro do intervalo permitido, a resposta retornada pelo servidor terá vários outros campos de cabeçalho:

  Access-Control-Allow-Origin: http://api.bob.com

  Access-Control-Allow-Credentials: true

  Access-Control-Expose-Headers: FooBar

  Content-Type: text/html; charset=utf-8

Entre as informações do cabeçalho acima, há três campos relacionados a solicitações CORS, todos começando com Access-Control-

**Access-Control-Allow-Origin* : Este campo é obrigatório. Seu valor é o valor do campo Origem no momento da requisição, ou um , indicando que requisições de qualquer nome de domínio são aceitas

Access-Control-Allow-Credentials : Este campo é opcional. Seu valor é um booleano que indica se os cookies podem ser enviados. Por padrão, os cookies não são incluídos nas solicitações CORS. Se estiver definido como true, significa que o servidor permite expressamente que o Cookie possa ser incluído na solicitação e enviado ao servidor em conjunto. Este valor só pode ser definido como verdadeiro.Se o servidor não quiser que o navegador envie cookies, basta excluir este campo.

Access-Control-Expose-Headers : Este campo é opcional. Quando o CORS solicita, o método 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 em Access-Control-Expose-Headers.

atributo withCredentials

Conforme mencionado acima, as solicitações 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, você precisa que o servidor concorde em especificar o campo Access-Control-Allow-Credentials.

Por outro lado, os desenvolvedores devem ativar o atributo withCredentials em solicitações AJAX.

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

// 前端设置是否带cookie

xhr.withCredentials = true;

xhr.open('post', 'http://www.domain2.com:8080/login', true);

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.send('user=admin');

xhr.onreadystatechange = function() {
    
    

    if (xhr.readyState == 4 && xhr.status == 200) {
    
    

        alert(xhr.responseText);

    }

};
// jquery

$.ajax({
    
    

        ...

       xhrFields: {
    
    

             withCredentials: true    // 前端设置是否带cookie

       },

       crossDomain: true,  // 会让请求头中包含跨域的额外信息,但不会含cookie

        ...

});

Caso contrário, mesmo que o servidor concorde em enviar o cookie, o navegador não o enviará. Ou o servidor exige que os cookies sejam definidos e o navegador não os manipulará. No entanto, se a configuração withCredentials for omitida, alguns navegadores ainda enviarão cookies juntos. Neste ponto, withCredentials pode ser explicitamente desativado.

**Deve-se observar que, se você deseja enviar cookies, Access-Control-Allow-Origin não pode ser definido como um asterisco* e você deve especificar um nome de domínio claro que seja consistente com a página da Web solicitada. **Ao mesmo tempo, os cookies ainda seguem a mesma política de origem. Apenas os cookies definidos com o nome de domínio do servidor serão carregados, e os cookies de outros nomes de domínio não serão carregados, e o document.cookie no (origem cruzada ) o código original da página da web não pode ler o nome de domínio do servidor em Cookies.

2.2 Pedidos não simples

Uma solicitação não simples é uma solicitação que possui requisitos especiais no servidor, por exemplo, o método de solicitação é PUT ou DELETE ou o tipo do campo Content-Type é application/json.

Para solicitações CORS que não sejam solicitações simples, uma solicitação de consulta HTTP será adicionada antes da comunicação oficial, que é chamada de solicitação "preflight" (preflight) - o navegador primeiro pergunta ao servidor se o nome de domínio da página da web atual está em a lista de permissões do servidor e quais verbos HTTP e campos de cabeçalho podem ser usados. Somente quando uma resposta positiva for recebida, o navegador emitirá uma solicitação XMLHttpRequest formal, caso contrário, um erro será relatado.

var url = 'http://api.alice.com/cors';

var xhr = new XMLHttpRequest();

xhr.open('PUT', url, true);

xhr.setRequestHeader('X-Custom-Header', 'value');

xhr.send();

Quando o navegador descobre que se trata de uma solicitação não simples, ele envia automaticamente uma solicitação " preflight ", solicitando ao servidor que confirme se tal solicitação é possível. Abaixo estão os cabeçalhos HTTP para esta solicitação "preflight".

  OPTIONS /cors HTTP/1.1

  Origin: http://api.bob.com

  Access-Control-Request-Method: PUT

  Access-Control-Request-Headers: X-Custom-Header

  Host: api.alice.com

  Accept-Language: en-US

  Connection: keep-alive

  User-Agent: Mozilla/5.0...

O método de solicitação usado pela solicitação "preflight" é OPTIONS , indicando que esta solicitação é para consulta. Nas informações do cabeçalho, o campo-chave é Origem, indicando de qual origem vem a solicitação.

Além do campo Origin, o cabeçalho da solicitação "preflight" contém dois campos especiais.

Access-Control-Request-Method: Este campo é obrigatório e é usado para listar quais métodos HTTP serão usados ​​pela requisição CORS do navegador. O exemplo acima é PUT.

Access-Control-Request-Headers: Este campo é uma string separada por vírgula, especificando os campos de informações de cabeçalho adicionais que a solicitação CORS do navegador enviará, o exemplo acima é X-Custom-Header

Resposta à solicitação de simulação

Depois que o servidor recebe a solicitação de "pré-verificação", verifica os campos Origin, Access-Control-Request-Method e Access-Control-Request-Headers, confirma que as solicitações de origem cruzada são permitidas e, em seguida, responde

HTTP/1.1 200 OK

Date: Mon, 01 Dec 2008 01:15:39 GMT

Server: Apache/2.0.61 (Unix)

Access-Control-Allow-Origin: http://api.bob.com

Access-Control-Allow-Methods: GET, POST, PUT

Access-Control-Allow-Headers: X-Custom-Header

Content-Type: text/html; charset=utf-8

Content-Encoding: gzip

Content-Length: 0

Keep-Alive: timeout=2, max=100

Connection: Keep-Alive

Content-Type: text/plain

Na resposta HTTP acima, a chave é o campo Access-Control-Allow-Origin, indicando que http://api.bob.com pode solicitar dados. Este campo também pode ser definido como um asterisco, que concorda com qualquer solicitação de origem cruzada.

Se o navegador negar a solicitação "preflight", uma resposta HTTP normal será retornada, mas sem nenhum campo de cabeçalho relacionado ao CORS. Neste momento, o navegador determinará que o servidor não concorda com a solicitação de simulação, então um erro é acionado, o qual é capturado pela função onerror callback do objeto XMLHttpRequest. O console imprimirá uma mensagem de erro.

Outros campos relacionados ao CORS respondidos pelo servidor são os seguintes:

Access-Control-Allow-Methods: GET, POST, PUT

Access-Control-Allow-Headers: X-Custom-Header

Access-Control-Allow-Credentials: true

Access-Control-Max-Age: 1728000

Access-Control-Allow-Methods: Este campo é obrigatório e seu valor é uma string separada por vírgulas, indicando todos os métodos de requisição entre domínios suportados pelo servidor. Observe que todos os métodos suportados são retornados, não apenas aquele solicitado pelo navegador. Isso é para evitar várias solicitações "preflight".

Access-Control-Allow-Headers: O campo Access-Control-Allow-Headers é obrigatório se a solicitação do navegador incluir o campo Access-Control-Request-Headers. É também uma string separada por vírgula indicando todos os campos de cabeçalho suportados pelo servidor, não limitados aos solicitados pelo navegador em "preflight".

Access-Control-Allow-Credentials: Este campo tem o mesmo significado de uma solicitação simples.

Access-Control-Max-Age: Este campo é opcional e é usado para especificar o período de validade desta solicitação de simulação, em segundos. No resultado acima, o período de validade é de 20 dias (1.728.000 segundos), o que significa que a resposta pode ser armazenada em cache por 1.728.000 segundos (20 dias), período durante o qual outra solicitação de simulação não precisa ser enviada.

O navegador responde normalmente ao pedido

Depois que o servidor passar pela solicitação de "pré-verificação", todas as solicitações CORS normais do navegador serão iguais a uma solicitação simples e haverá um campo de cabeçalho Origin. A resposta do servidor também terá um campo de cabeçalho Access-Control-Allow-Origin.

PUT /cors HTTP/1.1

Origin: http://api.bob.com

Host: api.alice.com

X-Custom-Header: value

Accept-Language: en-US

Connection: keep-alive

User-Agent: Mozilla/5.0...

Uma solicitação CORS normal do navegador. O campo Origem 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.com

Content-Type: text/html; charset=utf-8

O campo Access-Control-Allow-Origin deve ser incluído em todas as respostas

3. Processamento entre domínios do Nodejs

3.1 A configuração permite nomes de domínio entre domínios

  • Defina para permitir todos os nomes de domínio entre domínios
var express = require('express');
var app = express();
 
// 设置允许所有域名跨域:
app.all("*",function(req,res,next){
    
    
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin","*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers","content-type");
    //跨域允许的请求方式 
    res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
    if (req.method.toLowerCase() == 'options')
        res.send(200);  //让options尝试请求快速结束
    else
        next();
})
  • Defina para permitir vários nomes de domínio entre domínios:
app.all("*",function(req,res,next){
    
    
  var orginList=[
      "http://www.bibi.com",
      "http://www.qq.com",
      "http://www.baidu.com"
  ]
  // 防止undefined 报错
  if(!req.headers.origin){
    
    
    return
  }
   if(orginList.includes(req.headers.origin.toLowerCase())){
    
    
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type");
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
        //设置允许跨域的域名,*代表允许任意域名跨域
        res.header("Access-Control-Allow-Origin",req.headers.origin);
        if (req.method.toLowerCase() == 'options'){
    
    
          res.sendStatus(200);  //让options尝试请求快速结束
        }
        else{
    
    
          next();
        }
    } else {
    
    
      res.sendStatus(500)
    }
})

3.2 Usando núcleos de middleware

instalar npm i cors -S

Uso 1: Habilitar cross-domain para todas as fontes

const  cors = require('cors')
 app.use(cors())
 app.listen(8000, function () {
    
    
   console.log('start')
 })

Método de uso 2: configurar por condição

 var express = require('express')
 var cors = require('cors')
 var app = express()
 var whitelist = ['http://example1.com', 'http://example2.com']
//  异步配置
  var corsOptions;
 var corsOptionsDelegate = function (req, callback) {
    
    
  if (whitelist.indexOf(req.header('Origin')) !== -1) {
    
    
    corsOptions = {
    
     origin: true} //在CORS响应中反映(启用)请求的起源
  } else {
    
    
     corsOptions = {
    
     origin: false} // 拦截请求
  }
  callback(null, corsOptions) //  error  options
}

 app.all("*", cors(corsOptionsDelegate), function (req, res, next) {
    
    
 if(corsOptions.origin  === true){
    
    
    if (req.method.toLowerCase() == 'options'){
    
    
      res.sendStatus(200);  //让options尝试请求快速结束
     }
     else{
    
    
      next();
     }
   } else {
    
    
    res.sendStatus(500); //被拦截
   }
 })
  app.post('/cors',(req,res)=> {
    
    
  res.send('ok')
})
 app.listen(8000, function () {
    
    
   console.log('start')
 })

Acho que você gosta

Origin blog.csdn.net/DSelegent/article/details/128130136
Recomendado
Clasificación