首页 数字经济

彻底搞懂跨域:原理、解决方案与实战避坑指南

分类:数字经济
字数: (7238)
阅读: (8444)
内容摘要:彻底搞懂跨域:原理、解决方案与实战避坑指南,

在 Web 开发中,跨域资源共享(CORS)是一个绕不开的话题。无论你是前端工程师还是后端工程师,都可能遇到过浏览器报出的“No 'Access-Control-Allow-Origin' header is present on the requested resource”错误。本文将深入探讨跨域产生的原因,提供多种解决方案,并分享一些实战中的避坑经验。

什么是跨域?

浏览器的同源策略(Same-Origin Policy)是一种重要的安全机制,用于限制一个源(origin)的文档或脚本与来自另一个源的资源进行交互。当协议、域名和端口号三者之一不同时,就认为两个 URL 不是同源的,从而触发跨域限制。例如,http://www.example.comhttps://www.example.com (协议不同), http://www.example.comhttp://api.example.com (域名不同), http://www.example.com:8080http://www.example.com:8081 (端口不同) 都属于跨域。

跨域的底层原理

同源策略主要限制以下几种行为:

彻底搞懂跨域:原理、解决方案与实战避坑指南
  • Cookie、LocalStorage 和 IndexDB 等数据的访问
  • DOM 访问
  • XMLHttpRequest (XHR) 或 Fetch API 的请求发送

浏览器在发起跨域请求时,会先发送一个预检请求(Preflight Request)到服务器,询问服务器是否允许该跨域请求。预检请求使用 OPTIONS 方法,并包含以下头部:

  • Origin: 发起请求的源
  • Access-Control-Request-Method: 实际请求使用的方法(例如 GET, POST, PUT, DELETE)
  • Access-Control-Request-Headers: 实际请求中使用的自定义头部

如果服务器返回的响应中包含了 Access-Control-Allow-Origin 头部,并且该头部的值与请求的源匹配,或者为 * (表示允许所有源),那么浏览器才会发送实际的请求。否则,浏览器会阻止该请求,并抛出跨域错误。

彻底搞懂跨域:原理、解决方案与实战避坑指南

常见的跨域解决方案

1. CORS(跨域资源共享)

CORS 是最常用的跨域解决方案。它通过在服务器端设置响应头部来允许跨域请求。以下是一个使用 Node.js 和 Express 实现 CORS 的示例:

const express = require('express');
const cors = require('cors'); // 引入 cors 中间件
const app = express();

app.use(cors()); // 使用 cors 中间件,允许所有来源的请求

app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from the API!' });
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

对于 Java Spring Boot 应用,可以使用 @CrossOrigin 注解或者全局配置:

彻底搞懂跨域:原理、解决方案与实战避坑指南
@RestController
@CrossOrigin(origins = "http://example.com") // 允许特定来源的请求
public class MyController {

    @GetMapping("/api/data")
    public String getData() {
        return "Hello from the API!";
    }
}

也可以在 Nginx 配置文件中添加以下配置,来允许跨域请求。在使用宝塔面板的服务器上,可以直接在站点配置中修改:

location /api/ {
    add_header 'Access-Control-Allow-Origin' "*"; # 允许所有来源
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    if ($request_method = OPTIONS) {
        return 204;
    }
}

2. JSONP

JSONP (JSON with Padding) 是一种较老的跨域解决方案,它利用了 <script> 标签可以跨域请求资源的特性。JSONP 的原理是动态创建 <script> 标签,并通过 URL 传递一个回调函数名。服务器端接收到请求后,将数据包裹在该回调函数中,返回给客户端。客户端执行该回调函数,从而获取数据。由于安全性问题,现在通常不推荐使用 JSONP。

彻底搞懂跨域:原理、解决方案与实战避坑指南
<script>
  function handleResponse(data) {
    console.log(data); // 处理返回的数据
  }

  const script = document.createElement('script');
  script.src = 'http://api.example.com/data?callback=handleResponse'; // 指定回调函数
  document.head.appendChild(script);
</script>

3. Nginx 反向代理

Nginx 可以作为反向代理服务器,将客户端的请求转发到不同的后端服务器。通过将前端和后端部署在同一个域名下,可以避免跨域问题。例如,可以将前端部署在 www.example.com,将后端 API 部署在 api.example.com。然后,配置 Nginx 将 www.example.com/api 的请求转发到 api.example.com

Nginx 反向代理还可以实现负载均衡,提高系统的并发连接数和可用性。以下是一个简单的 Nginx 反向代理配置:

server {
    listen 80;
    server_name www.example.com;

    location / {
        root /var/www/frontend;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://api.example.com; # 转发到后端 API
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

4. WebSocket

WebSocket 是一种全双工通信协议,可以在客户端和服务器之间建立持久连接。WebSocket 不受同源策略的限制,因此可以用于跨域通信。但是,WebSocket 需要服务器端支持 WebSocket 协议,并且需要使用特定的 WebSocket 客户端库。

跨域实战避坑经验

  • OPTIONS 请求被拦截:某些防火墙或安全策略可能会拦截 OPTIONS 请求,导致跨域请求失败。需要检查服务器的防火墙配置,确保允许 OPTIONS 请求。
  • Cookie 丢失:跨域请求默认情况下不会携带 Cookie。需要在服务器端设置 Access-Control-Allow-Credentials: true 头部,并在客户端的 XMLHttpRequest 对象中设置 withCredentials = true,才能携带 Cookie。注意,如果设置了 Access-Control-Allow-Credentials: true,则 Access-Control-Allow-Origin 不能设置为 *,必须指定具体的域名。
  • 预检请求缓存:浏览器会对预检请求进行缓存,避免频繁发送 OPTIONS 请求。可以通过设置 Access-Control-Max-Age 头部来控制预检请求的缓存时间。
  • 不同浏览器的兼容性:不同的浏览器对 CORS 的支持程度可能有所不同。需要进行充分的测试,确保在各种浏览器上都能正常工作。
  • 安全性考虑:在允许跨域请求时,需要仔细考虑安全性问题,避免恶意攻击。例如,可以对请求进行身份验证和授权,限制可以访问的资源。

理解跨域的原理并选择合适的解决方案,可以有效地解决 Web 开发中的跨域问题。希望本文能够帮助你更好地理解和应用跨域技术。

彻底搞懂跨域:原理、解决方案与实战避坑指南

转载请注明出处: 半杯凉茶

本文的链接地址: http://m.acea4.store/blog/554100.SHTML

本文最后 发布于2026-03-29 18:01:16,已经过了29天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 土豆泥选手 6 天前
    JSONP现在基本不用了吧,感觉安全性太差了,容易被XSS攻击。
  • 麻辣烫 3 天前
    WebSocket 跨域确实是个好办法,但感觉配置起来稍微复杂一些,学习成本略高。
  • 工具人 4 小时前
    JSONP现在基本不用了吧,感觉安全性太差了,容易被XSS攻击。
  • 太阳当空照 1 天前
    讲的真透彻,特别是Nginx反向代理那块,解决了我的燃眉之急!