跨域的解决方案

一、概念

1. 浏览器的同源策略

浏览器为确保资源的安全,而遵循的一种策略。

2. 源

源 = 协议 + 域名 + 端口

3. 同源和非同源

当两个源只有他们的协议、域名、端口都一致,才是同源,否则是非同源。

4. 同源请求和非同源请求

如果是同源发出的请求就是同源请求,如果是非同源发出的请求就是非同源请求。

5. 跨域

所处源\] 与 \[目标源\] 不一致,就会导致跨域。 ## 二、浏览器会对跨域做哪些限制 \[源 A\] 和 \[源 B\]是非同源的,则浏览器会有以下限制。 ### 1. DOM 访问限制 \[源 A\]的脚本不能读取和操作\[源 B\]的 DOM ### 2. Cookie 访问限制 \[源 A\]不能访问\[源 B\]的 Cookie ### 3. Ajax 响应数据限制 \[源 A\]可以给\[源 B\]发请求,但无法获取\[源 B\]的返回的数据 ## 三、注意点 跨域限制仅存在浏览器端,服务端不存在跨域限制 即时跨域了,Ajax 请求也可以正常发出,但响应数据不会交给开发者。 \、\、\...这些标签发出的请求也可能跨域,只不过浏览器对标签不做严格限制,对开发几乎无影响。 ## 四、CORS 解决跨域 CORS 即跨源资源共享(Cross-Origin Resource Sharing),CORS 是一种机制,它允许 Web 应用服务器进行跨域访问控制,使不同源的网站之间能够安全地共享资源。 在默认情况下,出于安全考虑,浏览器会限制从一个源(协议、域名、端口)加载的脚本获取或操作另一个源的资源。而 CORS 为 Web 应用提供了一种安全的方式来绕过这种同源策略的限制。 使用 CORS 解决跨域是最正统的方式,且要求服务器是"自己人" ### 1. 简单请求和复杂请求 **简单请求** > **请求方式:**GET、HEAD、POST > > **Content-type:**text/plain、multipart/form-data、application/x-www-form-urlencoded 请求头字段符合《CORS 安全规范》,只要你改了请求头就变复杂请求了。 **复杂请求** 不是简单请求就是复杂请求,复杂请求会自动发送预检请求。 ### 2. 解决简单请求 以 nodeJS 为例,服务器端设置响应头 Access-Control-Allow-Origin,值为发送请求的源表示,只要从这个源发送的请求,都通过。值为 "\\\*" 表示所有不同源发来的请求都通过。 ```javascript app.get("/xxx", (res, req) => { res.setHeader("Access-Control-Allow-Origin", "发送请求源" | "*"); res.send(); }); ``` ### 3. 解决复杂请求 以 nodeJS 为例,服务器设置响应头,与请求头一一对应,使用 cors 插件。 ```javascript app.use( cors({ origin: "xxx", // 允许源 methods: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"], // 允许方法 allowedHeaders: ["xxx"], // 允许的自定义头 exposedHeaders: ["xxx"], // 要暴露的响应头 }) ); app.get("/xxx", (res, req) => { res.setHeader("xxx", "xxx"); res.send(); }); ``` ## 五、JSONP 解决跨域 JSONP 利用\标签可以跨域加载脚本,且不受严格模式限制的特性。 ### 1. 基本流程 > **第一步:**创建 script 标签,将 src 设置为跨域请求的 url。同时准备一个回调函数,这个函数处理返回来的数据。 > > **第二步:**服务端接受到请求后,将数据封装在回调函数中返回 > > **第三步:**客户端回调函数被调用,数据以参数的形式传入回调函数 ### 2. 例子 **服务端代码** ```javascript let list = [1, 2, 3]; app.get("/table", (req, res) => { const { callback } = req.query; res.send(`${callback}(${JSON.stringify(list)})`); }); ``` **客户端代码** ```javascript function test(data) { console.log(data); } function getTable() { const script = document.createElement("script"); script.onload = () => { script.remove(); }; script.src = "http://xxx.xx.xx:8080/table?callback=test"; document.body.appendChild(script); } ``` ## 六、配置代理解决跨域 ### **1. 自己配置代理服务器** 借助 http-proxy-middleware 配置代理 ```javascript const { createProxyMiddleware } = require("http-proxy-middleware"); app.use( "/api", createProxyMiddleware({ target: "https://www.baidu.com", changeOrigin: true, pathRewrite: { "^/api": "", }, }) ); ``` ### 2. 使用 Nginx 搭建代理服务器 #### 2.1 设置响应头 ```javascript server { listen 80; server_name your_domain.com; location /api/ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; if ($request_method = 'OPTIONS') { return 204; } proxy_pass http://your_backend_server; } } ``` #### 2.2 反向代理 通过 Nginx 将跨域请求代理到目标服务器,让浏览器认为是同源请求。 ```javascript server { listen 80; server_name frontend.com; location /api/ { proxy_pass http://backend.com; } } ``` ### 3. 脚手架服务器 比如 vue3 里的配置文件 **vite.config.js** 可以配置代理的地址 ```javascript import { defineConfig } from "vite"; // https://vitejs.dev/config/ export default defineConfig(() => { return { server: { host: "127.0.0.1", port: 8081, strictPort: false, open: true, proxy: { "/dev-api": { target: "http://localhost:1112", changeOrigin: true, rewrite: (path) => path.replace(/^\/dev-api/, ""), }, }, }, }; }); ```

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax