Compartilhamento de tecnologia

Compreenda completamente o domínio cruzado de front-end

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

 

Índice

1Política de mesma origem do navegador

1.1 Visão Geral da Política de Mesma Origem

1.2 O que é origem?

2. Quais são as restrições às transações entre domínios?

2.1 Restringir acesso ao DOM

2.2 Restringir acesso a cookies

2.3 Limite o Ajax para obter dados

3 pontos a serem observados

4CORS resolve problemas de domínio cruzado do Ajax

4.1 Visão Geral do CORS

4.2CORS resolve solicitações simples entre domínios

4.3 Solicitações simples e solicitações complexas

4.4CORS resolve solicitações complexas entre domínios

4.5 Use a biblioteca cors para concluir rapidamente a configuração

5JSONP resolve problemas entre domínios

6Configure o proxy para resolver problemas entre domínios

6.1 Configure você mesmo o servidor proxy

6.2 Use Nginx para construir um servidor proxy

6.3 Construir um servidor com ajuda de andaimes


Endereço de código git clone https://gitee.com/childe-jia/cross-domain-test.git

1Política de mesma origem do navegador

1.1 Visão Geral da Política de Mesma Origem


A política de mesma origem é uma política que os navegadores seguem para garantir a segurança dos recursos. Esta política impõe algumas restrições ao acesso aos recursos.
Descrição da política de mesma origem do W3C:Política de mesma origem

1.2 O que é origem?


1 componentes de origem

imagem.png


2Na tabela abaixo, apenas as duas fontes da última linha têm a mesma origem.

Fonte 1

Fonte 2

É homólogo?

http://www.xyz.com/home

https://www.xyz.com/home

⛔Não homogêneo️

http://www.xyz.com/home

http://mail.xyz.com/home

⛔Não homogêneo

http://www.xyz.com:8080/home

http://www.xyz.com:8090/home

⛔Não homogêneo

http://www.xyz.com:8080/home

http://www.xyz.com:8080/search

✅Mesma origem︎

 

3 solicitação de origem

imagem.png


4 Solicitação não original

imagem.png


5 Resumo: Se a "fonte" for inconsistente com a "fonte alvo", significa "não fonte", também conhecida como "heterofonte" ou "domínio cruzado"

2. Quais são as restrições às transações entre domínios?


Por exemplo, se houver duas fontes: "Fonte A" e "Fonte B", que são de "origem diferente", o navegador terá as seguintes restrições:

2.1 Restringir acesso ao DOM

O script da “Fonte A” não pode acessar o DOM da “Fonte B”.

  1. <!-- <iframe id="framePage" src="./demo.html"></iframe> -->
  2. <iframe id="framePage" src="https://www.baidu.com"></iframe>
  3. <script type="text/javascript" >
  4. function showDOM(){
  5. const framePage = document.getElementById('framePage')
  6. console.log(framePage.contentWindow.document) //同源的可以获取,非同源的无法获取
  7. }
  8. </script>

2.2 Restringir acesso a cookies

A "Fonte A" não pode acessar o cookie da "Fonte B"

  1. <iframe id="baidu" src="http://www.baidu.com" width="500" height="300"></iframe>
  2. <script type="text/javascript" >
  3. // 访问的是当前源的cookie,并不是baidu的cookie
  4. console.log(document.cookie)
  5. </script>

2.3 Limite o Ajax para obter dados

A "Fonte A" pode enviar solicitações para a "Fonte B", mas não pode obter os dados de resposta da "Fonte B".

  1. const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
  2. let result = await fetch(url)
  3. let data = await result.json();
  4. console.log(data)

Nota: Entre as restrições acima, a restrição do navegador à aquisição de dados Ajax tem o maior impacto e é frequentemente encontrada no desenvolvimento real.

3 pontos a serem observados

  • 1As restrições entre domínios existem apenas no lado do navegador e não há restrições entre domínios no lado do servidor.
  • 2 Mesmo que seja entre domínios, as solicitações Ajax podem ser emitidas normalmente, mas os dados de resposta não serão entregues ao desenvolvedor.
  • 3<link> , <script>、<img>...... 这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响

imagem.png

4CORS resolve problemas de domínio cruzado do Ajax

4.1 Visão Geral do CORS

O nome completo do CORS: Cross-Origin Resource Sharing (Cross-Origin Resource Sharing) é um conjunto de especificações usadas para controlar a verificação do navegador de solicitações entre domínios. O servidor segue a especificação CORS e adiciona cabeçalhos de resposta específicos para controlar a verificação do navegador. As regras gerais são as seguintes:
●O servidor rejeita explicitamente solicitações entre domínios ou não indica isso, e o navegador falha na verificação.
●O servidor indica claramente que as solicitações entre domínios são permitidas e a verificação do navegador é aprovada.
Nota: Usar o CORS para resolver problemas entre domínios é a maneira mais ortodoxa e requer que o servidor seja "próprio".


4.2CORS resolve solicitações simples entre domínios

A ideia geral: quando o servidor responde, ele expressa claramente que uma determinada fonte tem permissão para iniciar solicitações entre domínios adicionando o cabeçalho de resposta Access-Control-Allow-Origin e, em seguida, o navegador passa diretamente durante a verificação.

imagem.png

Código principal do lado do servidor (tome a estrutura expressa como exemplo):

  1. // 处理跨域中间件
  2. function corsMiddleWare(req,res,next){
  3. // 允许 http://127.0.0.1:5500 这个源发起跨域请求
  4. // res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')
  5. // 允许所有源发起跨域请求
  6. res.setHeader('Access-Control-Allow-Origin','*')
  7. next()
  8. }
  9. // 配置路由并使用中间件
  10. app.get('/',corsMiddleWare,(req,res)=>{
  11. res.send('hello!')
  12. })

4.3 Solicitações simples e solicitações complexas

O CORS divide as solicitações em duas categorias: ① solicitações simples e ② solicitações complexas.

pedido simples

Solicitação complexa

✅O método de solicitação (método) é: GET, HEAD, POST

1 é uma solicitação simples ou uma solicitação complexa.
2 Solicitações complexas enviarão automaticamente solicitações de simulação.

✅Os campos do cabeçalho da solicitação devem estar em conformidade com"Especificação de segurança CORS"
Nota curta: Contanto que o cabeçalho da solicitação não seja modificado manualmente, ele geralmente pode estar em conformidade com esta especificação.

✅O valor Content-Type do cabeçalho da solicitação só pode ser os três seguintes:
●texto/simples
●multipart/form-data
●aplicativo/x-www-form-urlencoded

Em relação às solicitações de simulação:

  • 1Tempo de envio: a solicitação de simulação é enviada antes da solicitação real entre domínios e é iniciada automaticamente pelo navegador.
  • 2 Função principal: Usada para confirmar com o servidor se a próxima solicitação entre domínios será permitida.
  • 3Processo básico: primeiro inicie uma solicitação OPTIONS. Se passar na pré-verificação, continue a iniciar a solicitação real entre domínios.
  • 4 Conteúdo do cabeçalho da solicitação: uma solicitação de simulação OPTIONS geralmente contém os seguintes cabeçalhos de solicitação:

Cabeçalho da solicitação

significado

Origem

A origem da solicitação

Método de solicitação de controle de acesso

O método HTTP real solicitado

Cabeçalhos de solicitação de controle de acesso

Cabeçalhos personalizados usados ​​na solicitação real (se houver)

4.4CORS resolve solicitações complexas entre domínios

1 Etapa um: O servidor primeiro passa a solicitação de simulação do navegador. O servidor precisa retornar o seguinte cabeçalho de resposta:

cabeçalho de resposta

significado

Acesso-Controle-Permitir-Origem

fontes permitidas

Métodos de permissão de controle de acesso

métodos permitidos

Acesso-Controle-Permitir-Cabeçalhos

Cabeçalhos personalizados permitidos

Controle de acesso-Idade máxima

Tempo de armazenamento em cache de resultados para solicitações de simulação (opcional)

imagem.png

2 Etapa 2: lidar com a solicitação real entre domínios (da mesma forma que você lida com solicitações simples entre domínios)

imagem.png

Código principal do servidor:

  1. // 处理预检请求
  2. app.options('/students', (req, res) => {
  3. // 设置允许的跨域请求源
  4. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  5. // 设置允许的请求方法
  6. res.setHeader('Access-Control-Allow-Methods', 'GET')
  7. // 设置允许的请求头
  8. res.setHeader('Access-Control-Allow-Headers', 'school')
  9. // 设置预检请求的缓存时间(可选)
  10. res.setHeader('Access-Control-Max-Age', 7200)
  11. // 发送响应
  12. res.send()
  13. })
  14. // 处理实际请求
  15. app.get('/students', (req, res) => {
  16. // 设置允许的跨域请求源
  17. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  18. // 随便设置一个自定义响应头
  19. res.setHeader('abc',123)
  20. // 设置允许暴露给客户端的响应头
  21. res.setHeader('Access-Control-Expose-Headers', 'abc')
  22. // 打印请求日志
  23. console.log('有人请求/students了')
  24. // 发送响应数据
  25. res.send(students)
  26. })

4.5 Use a biblioteca cors para concluir rapidamente a configuração

Na configuração acima, você mesmo precisa configurar o cabeçalho de resposta ou encapsular manualmente o middleware. Com a biblioteca cors, você pode concluir a configuração de forma mais conveniente.

●Instalar cors

npm i cors

●Cors de configuração simples

app.use(cors())

●Configurar completamente o cors

  1. // cors中间件配置
  2. const corsOptions = {
  3. origin: 'http://127.0.0.1:5500', // 允许的源
  4. methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
  5. allowedHeaders: ['school'], // 允许的自定义头
  6. exposedHeaders: ['abc'], // 要暴露的响应头
  7. optionsSuccessStatus: 200 // 预检请求成功的状态码
  8. };
  9. app.use(cors(corsOptions)); // 使用cors中间件

Por padrão, js não pode acessar o cabeçalho de resposta definido pelo backend e precisa ser exposto pelo backend.

5JSONP resolve problemas entre domínios

Visão geral do 1JSONP: JSONP usa<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域。


2Processo básico:

  • ○Etapa um: O cliente cria um<script>标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
  • ○Etapa 2: Após receber a solicitação, o servidor encapsula os dados na função de retorno de chamada e os retorna.
  • ○Etapa 3: A função de retorno de chamada do cliente é chamada e os dados são passados ​​para a função de retorno de chamada na forma de parâmetros.

3Ilustração:

imagem.png

4 exemplos de código:

  1. <button onclick="getTeachers()">获取数据</button>
  2. <script type="text/javascript" >
  3. function callback(data){
  4. console.log(data)
  5. }
  6. function getTeachers(url){
  7. // 创建script元素
  8. const script = document.createElement('script')
  9. // 指定script的src属性
  10. script.src= 'http://127.0.0.1:8081/teachers'
  11. // 将script元素添加到body中触发脚本加载
  12. document.body.appendChild(script)
  13. // script标签加载完毕后移除该标签
  14. script.onload = ()=>{
  15. script.remove()
  16. }
  17. }
  18. </script>

5jQuery encapsulado jsonp

?callback=?' é um formato fixo e será analisado automaticamente

  1. $.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=>{
  2. console.log(data)
  3. })

6Configure o proxy para resolver problemas entre domínios

6.1 Configure você mesmo o servidor proxy

Não há problemas de domínio cruzado entre servidores. Você precisa usar expresso para iniciar recursos estáticos para garantir que seu servidor e sua página estejam na mesma origem.

  1. // 启动静态资源 让服务器跟页面同一个源
  2. app.use(express.static("./public"));

Configurar proxy com http-proxy-middleware

  1. const { createProxyMiddleware } = require('http-proxy-middleware');
  2. app.use('/api',createProxyMiddleware({
  3. target:'https://www.toutiao.com',
  4. changeOrigin:true,
  5. pathRewrite:{
  6. '^/api':''
  7. }

 

vantagem:

  • Funções avançadas: http-proxy-middleware oferece diversas opções de configuração para atender a diversas necessidades de proxy.
  • Configuração flexível de vários proxies: Vários servidores proxy podem ser configurados, correspondendo a diferentes caminhos de interface.
  • Pode interceptar solicitações: as solicitações podem ser interceptadas e modificadas por meio de funções de processamento personalizadas.

deficiência:

  • A configuração é relativamente complexa: você precisa entender as regras e parâmetros de configuração da biblioteca http-proxy-middleware.
  • Não é adequado para ambientes de produção: http-proxy-middleware é usado principalmente em ambientes de desenvolvimento e não é adequado para ambientes de produção.

cenas a serem usadas:

  • Adequado para projetos front-end usando qualquer ferramenta de construção e funciona com qualquer servidor de desenvolvimento.
  • Adequado para cenários onde vários servidores proxy precisam ser configurados de forma flexível.
  • Adequado para cenários onde as solicitações precisam ser interceptadas e modificadas.

6.2 Use Nginx para construir um servidor proxy

A ideia geral: deixar o nginx desempenhar duas funções, tanto como servidor de conteúdo estático quanto como servidor proxy.

Modifique a configuração do nginx da seguinte maneira. Observe que o diretório raiz do nginx não é preferencialmente a unidade C.

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. }
  6. # 配置代理
  7. location /dev/ {
  8. # 设置代理目标
  9. proxy_pass http://sph-h5-api.atguigu.cn/;
  10. }

2 Modifique o projeto front-end para que todas as solicitações sejam encaminhadas para /dev e depois reembaladas

  1. const request = axios.create({
  2. baseURL:'/dev',
  3. timeout:10000
  4. })

Em seguida, acesse diretamente o servidor nginx. Por exemplo, se o nginx estiver rodando na porta 8099, acesse.

http://localhost:8099

Então você encontrará o problema de atualização 404, adicione a configuração nginx para resolvê-lo

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. try_files $uri $uri/ /index.html; # 解决刷新404
  6. }
  7. # 配置代理
  8. location /dev/ {
  9. # 设置代理目标
  10. proxy_pass http://sph-h5-api.atguigu.cn/;
  11. }

Adicionar esses dois "/" elimina dev

6.3 Construir um servidor com ajuda de andaimes

1. Use o arquivo vue.config.js para configurar o proxy:

Crie um arquivo vue.config.js no diretório raiz do projeto Vue e adicione o seguinte código:

  1. module.exports = {
  2. devServer: {
  3. proxy: {
  4. '/api': {
  5. target: 'http://api.example.com',
  6. changeOrigin: true,
  7. pathRewrite: {
  8. '^/api': ''
  9. }
  10. }
  11. }
  12. }
  13. }

No código acima, usamosdevServer Itens de configuração para configurar o servidor proxy.emproxyAs propriedades são usadas para configurar as regras do proxy,/apiIndica o caminho da interface que requer proxy.targetO atributo representa o endereço do servidor de destino do proxy,changeOriginO atributo indica se o endereço de origem da solicitação deve ser alterado.pathRewritePropriedade usada para substituir o caminho solicitado.

vantagem:

  • Configuração simples: Usando a configuração de proxy do webpack-dev-server, você só precisa realizar uma configuração simples no arquivo de configuração do webpack.
  • Funcionalidade abrangente: webpack-dev-server oferece diversas opções de configuração para atender à maioria das necessidades de proxy.
  • Pode interceptar solicitações: as solicitações podem ser interceptadas e modificadas por meio de funções de processamento personalizadas.

deficiência:

  • O servidor precisa ser reiniciado: Após a modificação da configuração, o webpack-dev-server precisa ser reiniciado para ter efeito.
  • Não é adequado para ambientes de produção: webpack-dev-server é usado principalmente em ambientes de desenvolvimento e não é adequado para ambientes de produção.

cenas a serem usadas:

  • É adequado para projetos front-end construídos usando webpack e iniciando o servidor de desenvolvimento através de webpack-dev-server.
  • É adequado para cenários que exigem configuração de proxy simples e não precisam modificar a configuração do proxy com frequência.