LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【WEB开发】什么是“跨域”及跨域解决方案

admin
2025年2月21日 16:1 本文热度 308
什么是跨域

跨域是指从一个域名的网页去请求另一个域名的资源。比如,从www.a.com域名的网页去请求www.b.com域名的资源,只要协议、域名、端口有任何一个不同,都被当作是不同的域,跨域问题通常由浏览器的同源策略引起的。

同源策略就是浏览器出于安全考虑而制定的,例如数据安全,服务器安全,减少 xss(跨站脚本攻击),CSRF(跨站请求伪造) 等攻击。所谓同源,就是协议,域名,端口号都相同才能请求数据。如果是非同源请求发送后,浏览器会拦截响应。

  1. 浏览器出于安全考虑(数据安全,服务器安全,减少 xss,CSRF 攻击)  2. https://    www.     abc.com    :8000     /a.html      协议      子域名     主域名     端口号   路径  3. 非同源,请求发送后,浏览器会拦截响应

跨域解决方案

1.jsonp

  1. 借助 script 标签 src 属性不受同源策略的限制(经常要加载第三方库等),来发送请求
  2. 携带一个参数 callback 给后端
  3. 后端将数据作为 callback 函数的实参,返回给前端一个 callback 的调用形式
  4. 浏览器接收到 callback 的调用会自动执行全局的callback函数

代码具体实现如下:
// 前端<button onclick="handle()">请求</button>
<script>    function jsonp(url, cb) {      return new Promise((resolve, reject) => {
        const script = document.createElement('script')
        // 定义一个全局函数,用来接收后端返回的数据        window[cb] = function (data) {          // console.log(data) // 后端返回的数据          resolve(data)        }
        script.src = `${url}?cb=${cb}`
        // 将标签加到document.body时,浏览器就会发url请求        document.body.appendChild(script)          // callback('hello world')      })    }
    function handle() {      jsonp('http://localhost:3000', 'callback').then(res => {        console.log(res)      })    } </script>
前端通过一个jsonp函数,传入请求的url和回调函数的名称cb,然后在jsonp函数里面创建一个script标签,将该标签的src属性变为url后面用?拼接传入的字符串。
// 后端const http = require('http');
http.createServer((req, res) => {  // 获取前端传过来参数  const query = new URL(req.url, `http://${req.headers.host}`).searchParams
  if (query.get('cb')) {    const cb = query.get('cb')  // 'callback'    const data = 'hello world'    const result = `${cb}("${data}")`   // "callback('hello world')"    res.end(result)  }
}).listen(3000);

后端创建一个http服务器,解析前端传过来的callback字符串参数,将数据作为参数返回"callback('hello world')"格式的一个函数。

缺点:

  • 必须要前后端配合
  • 只能发送 get 请求
  • 不安全,容易受到xss攻击

2. CORS(跨资源共享)

服务器在响应头中后端设置 Access-Control-Allow-Origin: '域名白名单',告诉浏览器允许哪个源进行跨域访问。可以是具体的域名,也可以是*表示允许所有源。如下

const http = require('http')
const server = http.createServer((req, res) => {  res.writeHead(200, {    'Access-Control-Allow-Origin''*',    // 允许所有域名访问    // 也可自行设置指定的域名可以访问     // 例如: 'Access-Control-Allow-Origin': 'http://192.168.2.1:5500'  })  res.end('hello world');})
server.listen(3000)
还可设置允许的请求方式和请求头等。

3.nginx反向代理

前端服务器和后端服务器不在同一个域名下, 前端服务器通过nginx 反向代理来访问后端服务器。

服务器和服务器之间的通信不存在跨域,可以开一台中间服务器(nginx),后端无需改变。前端把请求发给nginx , nginx 服务器把请求转发给后端的服务器,后端的服务器响应给 nginx 服务器,nginx 服务器加上响应头以后,再返回给前端,如下;

4. node 中间件代理

原理同nginx 反向代理,只不过多写一个node后端,前端服务器和后端服务器不在同一个域名下,前端服务器通过 node 中间件来访问后端服务器。

5. websocket

  1. 传统的前后端通信是基于http协议的,是单向的,只能从一端发到另一端,无法双向通信
  2. websocket 是基于tcp协议的,是双向的,可以从一端发送到另一端,也可以从另一端发送到一端
  3. socket协议一旦建立连接,就可以一直保持通信状态,不需要每次都建立连接,但是会更开销性能
  4. 天生就可以跨域

// 前端<script>    function WebSocketTest(url, params = {}) {      return new Promise((resolve, reject) => {
        // 创建socket实例对象        const socket = new WebSocket(url)
        // 当连接打开时发送数据        socket.onopen = () => {          socket.send(JSON.stringify(params))        }
        // 接收到后端的消息时打印数据并解决Promise        socket.onmessage = (event) => {          console.log(event.data)          resolve(event.data)        }      })    }
    WebSocketTest('ws://localhost:3000', { age: 18 }).then(res => {      console.log(res)    })  </script>
后端: 首先安装ws:npm i ws
// 后端
const WebSocket = require('ws');
// 在 3000 端口上建立 WebSocket 伺服器 (随时都在线的服务)const ws = new WebSocket.Server({ port: 3000 });
let count = 0
// 监听连接ws.on('connection', (obj) => {  // console.log(obj);  obj.on('message', (msg) => {  // 收到客户端发来的消息    // console.log(msg.toString());   // 客户端传过来的数据    obj.send('收到了')
    setInterval(() => {      count++      obj.send(count)    }, 2000)
  })})

6. postMessage

当父级页面和iframe页面不在同一个域名下,他们之间的数据传输也存在跨域问题,父级页面和iframe页面之间可以通过posMessage来通信。

<h2>首页</h2><iframe id="frame" src="http://127.0.0.1:5500/%E8%B7%A8%E5%9F%9F/postMessage/detail.html"frameborder="0" width="800" height="500"></iframe>
<script>    let obj = { name'阿杰'age18 }
    document.getElementById('frame').onload = function () {      this.contentWindow.postMessage(obj, 'http://127.0.0.1:5500'// 向iframe发送消息
      window.onmessage = function (e) { // 接收iframe发送的消息        console.log(e.data);      }
    }  </script>
<h3>详情页 --- <span id="title"></span></h3>
<script>    const title = document.getElementById("title");    window.onmessage = function (e) {  // 接收父级页面传过来的数据      // console.log(e.data);      title.innerText = e.data.age;      e.source.postMessage("阿杰 20了", e.origin)  // 向父级页面发送消息    }  </script>

7.document.domain

通过设置document.domain来允许同一主域名下的跨域通信,原理同postMessage,但是谷歌禁止了这种方法

总结

跨域是指从一个域名的网页去请求另一个域名的资源。只要协议、域名、端口有任何一个不同,都被当作是不同的域。跨域问题通常由浏览器的同源策略引起,同源策略是为了保证用户信息的安全,防止恶意网站窃取数据

同源策略浏览器出于安全考虑(数据安全,服务器安全,减少 xss,CSRF 攻击)而制定的一种只有协议、域名、端口号都相同才能请求数据的规定,非同源请求发送后,浏览器会拦截响应。

跨域方案

  1. jsonp(script标签的src属性不受同源策略的限制)
  2. CORS(跨资源共享,通知浏览器哪些域名可以访问)
  3. nginx 反向代理
  4. node 中间件代理
  5. websocket(socket协议可以保持长时间的连接,不受同源的限制,天生可以跨域)
  6. postMessage(父级页面和iframe页面之间可以通过posMessage来通信)
  7. document.domain(通过设置来允许同一主域名下的跨域通信,谷歌禁止了)

常见的解决方案有:CORS适用于需要支持多种HTTP方法(如GET、POST、PUT等)的现代Web应用,nginx 反向代理适用于前后端分离的项目,可以在服务器层面统一处理跨域问题。


该文章在 2025/2/21 16:01:37 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved