普通视图

发现新文章,点击刷新页面。
昨天以前首页

项目中遇到浏览器跨域前端和后端解决方案以及大概过程

作者 干就完了1
2025年4月2日 18:29

前言: ‌浏览器出于安全考虑,要求请求的 ‌协议(HTTP/HTTPS)、域名、端口(如 90/455 ‌ 三者完全一致,否则视为跨域。跨域问题的本质是 ‌浏览器通过同源策略保护用户数据安全‌,强制要求前后端资源同源。开发中因为环境分离、多域名部署等场景就会触发该策略的拦截机制‌。

一. 纯前端解决方案

1. ‌本地开发环境推荐使用代理解决‌‌

1.在Vue/React项目中配置 vue.config.js 或 webpack.config.js(vue3中是vite.config.ts文件)

//vue3的Vite示例
export default defineConfig({
  // 服务端渲染
    server: {
      // 端口号
      port: "8980",
      host: "0.0.0.0",
      // 本地跨域代理 http://192.145.1.95:1216
      proxy: {
        "/admin-api": {
          // 这里填写后端地址
          // target: "https://test.com",
          target: VITE_API_PATH, //或者封装起来
          changeOrigin: true,
          rewrite: path => path.replace(/^\/admin-api/, ""),
          secure: false // 验证 SSL 证书
        }
      },
    },
});
// vue2的webpack示例示例
module.exports = {
    devServer: {
        proxy: {
            '/admin-api': {
                target: 'https://test.com',
                changeOrigin: true
            }
        }
    }
};

// 不同的前端语言大致实现思路都一样

2.重启开发服务器,前端请求本地路径包含 /api 自动代理到后端接口地址。

2. ‌利用WebSocket协议解决‌‌

WebSocket 解决跨域的核心原理是在 HTTP 握手阶段通过服务器主动验证 Origin 字段完成跨域授权,而非依赖浏览器同源策略的默认拦截机制‌

1.前端使用WebSocket建立连接:

const socket = new WebSocket('ws://test.com:9090');
socket.onmessage = (event) => { console.log(event.data); };

2.后端需实现WebSocket服务端(如Socket.io)。

3.postMessage(跨窗口通信)

1.父窗口向iframe子窗口发送消息

const iframe = document.getElementById('child-frame');
iframe.contentWindow.postMessage('data', 'http://child.com');

2.子窗口监听消息:

window.addEventListener('message', (event) => {
    if (event.origin === 'http://parent.com') console.log(event.data);
});

二. 后端解决方案

1. ‌CORS(跨域资源共享)--->生产环境推荐 ‌‌

1.后端在响应头中设置 Access-Control-Allow-Origin,允许指定源访问:

// Spring Boot示例
@CrossOrigin(origins = "http://localhost:9090")
@GetMapping("/api/data")
public String getData() { /*...*/ }

2.若需携带Cookie,需设置 Access-Control-Allow-Credentials: true 并指定具体源(不能为*)。

3.预检请求(如PUT、DELETE)需处理OPTIONS方法,返回允许的HTTP方法和头信息。

2. ‌Nginx反向代理--->生产环境推荐‌‌

1.在Nginx配置文件中添加代理规则:

server {
    listen 90;
    server_name frontend.com;
    location /api {
        proxy_pass http://test.com:9090;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

2.重启Nginx服务,使前端通过统一域名访问后端接口

3. ‌JSONP(仅GET请求) ‌‌

1.前端动态创建<script>标签,指定回调函数名:

function handleData(data) { /*...*/ }
const script = document.createElement('script');
script.src = 'http://test.com/data?callback=handleData';
document.body.appendChild(script);

2.后端返回包裹回调函数的数据:

handleData({ "result": "success" });

三、其他场景方案

同主域不同子域‌:设置 document.domain = 'test.com'(需主域相同)‌

IE兼容性‌:使用XDomainRequest对象替代XMLHttpRequest‌

结尾

推荐方案‌:生产环境优先使用CORS或Nginx反向代理‌,开发环境用本地代理‌更方便快捷(配置简单且无侵入性‌)

慎用方案‌:JSONP仅适用于简单GET请求且安全性较低‌(需注意XSS风险‌),postMessage适用于特定跨窗口场景‌。

如果兄弟们还有其他更方便的解决方案欢迎评论区讨论分享,具体实现还需根据项目来定最适合的解决方案

❌
❌