跨域及解决方案

跨域(Cross-Origin)是指浏览器在执行 JavaScript 的时候,因为同源策略(Same-Origin Policy)的限制,阻止了一个网页去请求不同源(域名、端口、协议有任意一个不同)的资源。

1. 什么是同源策略?

  • 同源指:
  • 必须全部相同才算同源。
  • 只要有一个不同,就算跨域。

例子:

javascript 复制代码
当前页面地址:http://www.a.com:8080
以下都是跨域:
1. http://www.b.com:8080    // 不同域名
2. https://www.a.com:8080   // 不同协议
3. http://www.a.com:8081    // 不同端口

2. 跨域是如何造成的?

  • 跨域的根本原因是浏览器的安全限制。
  • 浏览器为了防止恶意网站窃取数据,不允许前端脚本直接读取其他源的响应数据。

注意:跨域限制只存在于浏览器端的 Ajax/Fetch 请求,后端请求(比如 Node.js 调用接口)是没有跨域限制的。

3. 前端开发常见跨域解决方案

  • 方案 1:CORS(最常用)
    • 核心原理:后端在响应头中加 Access-Control-Allow-Origin 等字段,告诉浏览器允许该域访问。

示例:

javascript 复制代码
Access-Control-Allow-Origin: http://www.a.com
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: Content-Type
  • 优点:标准、安全、灵活。
  • 缺点:需要后端配合。

  • 方案 2:JSONP(老旧方法,只支持 GET)
    • 原理:利用 <script>标签不受同源策略限制的特性,通过回调函数接收数据。

示例:

html 复制代码
<script src="http://api.b.com/data?callback=handleData"></script>
<script>
function handleData(data) {
    console.log(data);
}
</script>
  • 优点:简单,不需要改浏览器。
  • 缺点:只能 GET,请求安全性低,现在基本淘汰。

  • 方案 3:反向代理(本地开发常用)
    • 原理:在本地开发服务器(如 Webpack devServer、Vite、Nginx)配置代理,把请求转发到后端,避开浏览器跨域限制。

示例(vite.config.js):

javascript 复制代码
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://backend.com',
        changeOrigin: true,
        rewrite: path => path.replace(/^\/api/, '')
      }
    }
  }
}

示例(Nginx加 CORS 响应头):

bash 复制代码
server {
    listen 80;
    server_name www.example.com;

    location /api/ {
        proxy_pass http://api.example.com/;
        
        # 添加 CORS 头
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'Origin, Content-Type, Accept, Authorization';
        
        # 预检请求(OPTIONS)直接返回
        if ($request_method = OPTIONS) {
            return 204;
        }
    }
}

  • 方案 4:PostMessage / iframe
    • 原理:如果需要跨域页面之间通信,可以用 window.postMessage。
    • 用途:跨域 iframe、跨窗口通信。

  • 方案 5:跨域资源共享(特殊标签)
    • <img>, <script>, <link> 天生可以跨域加载资源,但不能直接获取内容(除非设置 CORS)。

  • 方案 6:同源策略的"放宽"
    • 修改浏览器配置(比如 Chrome 启动参数 --disable-web-security),但只建议本地调试,生产不可用。
相关推荐
risc1234564 分钟前
如何认识结构?结构 = 要素 + 关系 + 动态
笔记
PPPPPaPeR.6 分钟前
光学算法实战:深度解析镜片厚度对前后表面折射/反射的影响(纯Python实现)
开发语言·python·数码相机·算法
echoVic8 分钟前
多模型支持的架构设计:如何集成 10+ AI 模型
java·javascript
橙露9 分钟前
Java并发编程进阶:线程池原理、参数配置与死锁避免实战
java·开发语言
froginwe119 分钟前
C 标准库 - `<float.h>`
开发语言
程序员Agions11 分钟前
useMemo、useCallback、React.memo,可能真的要删了
前端·react.js
echoVic11 分钟前
AI Agent 安全权限设计:blade-code 的 5 种权限模式与三级控制
java·javascript
David凉宸13 分钟前
Vue 3 + TS + Vite + Pinia vs Vue 2 + JS + Webpack + Vuex:对比分析
javascript·vue.js·webpack
滕青山13 分钟前
Vue项目BMI计算器技术实现
前端·vue.js
子兮曰18 分钟前
深入浏览器指纹:Canvas、WebGL、Audio是如何暴露你的身份的?
前端·浏览器·canvas