首页/文章/http-网络

前端跨域问题及其解法方法

2023-12-25
273110 分钟
...

在前端项目的开发中,跨域 是我们必须要解决的问题,只要涉及到“向服务器请求资源”、“前后端交互”等功能,跨域 往往是无法避免的

那么什么是 跨域 问题,又该如何解决它呢?

跨域

导致 跨域 问题产生的根本原因来自浏览器的 同源策略

同源策略是浏览器的重要安全策略,它用于限制一个Origin的文档或者它加载的脚本如何能与另一个源的资源进行交互,其中Origin指Web文档的来源,Web 内容的来源取决于访问的URL的方案 (协议)主机 (域名)端口定义

简单来说在浏览器同源策略限制下,向不同源(不同协议、不同域名或者不同端口) 发送XHR请求时,浏览器认为该请求不受信任,可能存在安全隐患,禁止该请求,并作出不正常的响应

比如 www.baidu.comwww.baidu.com 间就会因协议不同而产生跨域问题

IE浏览器的同源策略比较特殊,IE未将端口号纳入同源策略的检查,同时对于两个高度互信的域名也不受同源策略的检查,比如公司域名

跨域的错误在项目开发的过程中尤为常见,当我们本地启动项目后,当前页面的域名和后台服务器域名不一致,就会引起 跨域,而在在项目上线后,会通过统一域名、后端配置域名白名单等方式避免跨域

跨域解诀方案:

解决 跨域 的方法多种多样,接下来让我们介绍几种常见的跨域解决方案

1.关闭浏览器同源策略

既然导致跨域的“罪魁祸首”是浏览器的同源策略,我们直接从根本入手不就解决问题了吗?

各大主流浏览器也确实提供了关闭同源策略的功能

IE浏览器:进入ie的网际网路选项设置,然后选择安全性,再选择自订等级,然后下拉,找到「存取跨网络的资料来源」,选择启用即可

chrome浏览器:首先需要关闭所有打开的浏览器窗口,在命令行窗口输入chrome --disable-web-security

FireFox浏览器:在地址栏输入about:config,然后下拉找到security.fileuri.strict_origin_policy,然后设置为false即可

这样的做法确实从根本上解决了跨域问题,但禁用同源策略会导致安全风险,所有并不推荐这样做

2.JSONP

在项目开发中常常会引入外链的图片、样式文件、插件等资源,但这些请求并没有导致跨域错误,因为这些请求都属于http请求 并不是会引发跨域 问题的Xhr 请求

简单来说script标签没有跨域限制的特性,把script脚本的src改成我需要跨域请求的url,就能实现跨域获取资源,且不触发浏览器的同源策略,这就是JSONP的原理

//前端
<script>
    window.callback = function (res) {
      console.log(res)
    }
  </script>
  <script src =' http://127.0.0.1:8080/jsonp?username=111&callback=callback'> </script>

const express = require('express')

const router = express.Router()
const app = express()
router.get('/jsonp', (req, res) => {
  const { callback, username } = req.query

  if (username === '111') {
    const requestData = {
      code: 200,
      status: '登录成功'
    }
    res.send(`${callback}(${JSON.stringify(requestData)})`)
  }

  
})

app.use(router)

app.listen('8080', () => {
  console.log('api server running at http://127.0.0.1:8080')
})

上面的代码中我们事先定义一个用于获取跨域响应数据的回调函数并挂载到window对象上,通过没有同源策略限制的script标签发起一个请求(将回调函数的名称放到这个请求的query参数里),然后服务端返回这个回调函数的执行,并将需要响应的数据放到回调函数的参数里,前端的script标签请求到这个执行的回调函数后会立马执行,于是就拿到了执行的响应数据

我们还可以在前端对JSONP代码进行一层封装

const requestData = {

![image.png](https:
url: 'http://127.0.0.1:8080/jsonp',

data: {

username: 111,

},

jsonp: 'getMessage'

}
function jsonp(requestData) {



const { url, data, jsonp } = requestData;

let query = '';

for (let key in data) {

query += `${key}=${data[key]}&`;

}

const src = `${url}?${query}jsonp=${jsonp}`;



let scriptTag = document.createElement('script');

scriptTag.src = src;

document.body.appendChild(scriptTag);

return new Promise((resolve, reject) => {

window[jsonp] = function(rest){

resolve(rest)

document.body.removeChild(scriptTag)

}

})

}


jsonp(requestData).then(function (response) {

console.log(response);

})

当然上述只是简单的JSONP实现,在实际的使用中JSONP还存在诸多问题:

1. CSRF攻击

当前端发起一个伪造的恶意JSONP请求时,服务端的敏感信息,如用户的个人信息,密码等存在泄露的风险,需要通过验证JSONP的调用来源(Referer),服务端判断 Referer 是否是白名单,或者部署随机 Token 来防御攻击

2.XSS漏洞

不严谨的 content-type类型会导致的 XSS 漏洞,如果没有严格定义好 Content-Type,例如 Content-Type: application/json,或者对请求url的query参数没有进行过滤,导致请求参数是一段恶意JavaScript代码,并被服务端接收执行并返回,那么前端就会执行这段恶意代码

通过严格定义 Content-Type: application/json,然后严格过滤 callback 后的参数并且限制长度(进行字符转义,例如<换成&lt,>换成&gt)等,这样返回的脚本内容会变成文本格式,脚本将不会执行

3.仅支持GET请求方式

JSOP 仅支持GET方式的请求,对于POST等其他请求方式并不能使用JSONP

3.CORS

Cross-Origin Resource sharing(跨域资源共享),是一种基于HTTP头的机制,该机制允许服务器标示除了它自己以外其他origin(域名,协议和端口),既浏览器在跨域的情景下仍然能从目标服务器请求并获取资源可以说CORS才是跨域问题的正统解决方案

前端任何对服务端发起的可能产生副作用的XHR类型的请求方法都会都会触发CORS中的预检机制,CORS因此将请求划分为了预检请求简单请求两种类型

CORS简单请求的策略是在请求时在请求头增加一个Origin字段,服务器收到请求后,根据该字段判断是否允许该请求访问,如果允许,在响应头信息中添加Access-Contro-Allow=Origin字段

简单请求需要满足以下规定:

1.请求方法必须是 GET POST HEAD 中的一种

2.头部字段必须满足CORS的安全规范

3.请求头的Content-Type字段值为以下三种之一

text/plainapplication/x-www-form-urlencodedmultipart/form-data

而对于预检请求CORS中通过预检机制(preflight request) 检查服务器是否允许浏览器发送真实请求,浏览器会先发送一个预检请求(option请求),请求中会携带真实请求的请求信息:

origin:请求的来源

Access-Control-Request-Method: 通知服务器在真正的请求中会采用哪种HTTP方法(GET,POST,DELETE...)

Access-Control-Request-Headers:通知服务器在真正的请求中会采用哪些请求头

服务端在收到预检请求后,会根据以上的请求信息,判断是否预检通过,这体现在服务端对预检请求返回的响应头


 res.header("Access-Control-Allow-Origin", "*"); 

 res.header("Access-Control-Allow-Credentials", "true"); 

 res.header("Access-Control-Allow-Headers", "X-Requested-With"); 

 res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); 
 
 res.header("Access-Control-Max-Age",t); 

当浏览器从预检请求的响应头中查找到以上的内容时,就会跳过同源策略,并允许真正的请求发送到服务端

4.服务器代理(ProxyServer)

同源策略主要是限制浏览器和服务器之间的请求,服务器与服务器之间并不存在跨域问题

前端将请求发送给同源或者设置好跨域的代理服务器,代理服务器收到代理请求后,将真正的请求转发到目标服务器,并接受其响应结果,再把接收到的结果响应给前端

总结

跨域问题的解决方案有很多种,我们可以根据实际情况来决定采用何种策略来解决跨域问题

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
http-网络2025-10-27
frp-内网穿透详解
1\. 简介与工作原理 frp(Fast Reverse Proxy)是一个高性能的反向代理 / 内网穿透工具。典型部署模式: 在 公网 VPS 上运行 (服务端),监听来自 的 出站持久连接 (控制端口,通常 7000)。 在 内网机器 上运行 (客户端),与 frps 建立长连接并注册若干映射(如 tcp/http)。 当外部请求到达 frps(公网),frps 根据路由规则把流量转发回对应的 frpc 连接,再由 frpc 转发到...
学习
http-网络2025-10-13
内网穿透介绍
&nbsp; 1\. 简要概念与为什么需要内网穿透 大多数家庭/公司网络在私有网(RFC1918)后面,通过 NAT 共享一个公网 IP。NAT 允许内网对外发起连接,但阻止公网主动连入。 内网穿透 就是建立从公网到内网的可达通道,常用于:Webhook 回调、远程演示、远程管理、IoT 设备接入、远程调试等。 2\. 核心原理(三行总结) 反向连接 :内网主动连到公网穿透服务器,建立一条"回路"。 中继/代理 :穿透服务器把外部流量中...
学习
http-网络2025-08-06
按下回车后网页是怎么出来的
当你在浏览器中输入一个网址,比如 ,然后按下回车键,几秒钟后页面就完整地呈现在你眼前。这个看似简单的操作,背后其实是一整套精密协作的网络机制在起作用。本文将带你从基础讲起,理解 Web 开发中最重要的网络知识,帮助你搞清楚: 数据是如何从服务器传到你的电脑,并最终变成网页的? 一、互联网通信的分层模型:OSI 七层模型 为了管理复杂的网络通信,工程师们提出了一个通用的参考模型—— OSI 七层模型 。它把整个通信过程划分为七个层次,每一...
学习面试
http-网络2025-06-20
MQTT与HTTP在物联网中的比较:为什么MQTT是更好的选择
简介: 通过上述分析,可以看出MQTT在物联网应用中的确是更好的选择。其高效的通信模型、低带宽消耗、稳定的连接保持机制以及可靠的消息质量保证,使其在各种物联网场景中都能表现出色。开发者在设计和实现物联网系统时,应优先考虑采用MQTT协议,以充分发挥其在资源受限环境下的优势,提升系统的整体性能和可靠性。 【杂谈】 MQTT与HTTP在物联网中的比较:为什么MQTT是更好的选择 在物联网(IoT)应用中,选择合适的通信协议是实现高效、可靠数...
学习
http-网络2025-03-04
网络代理详解
一、 的基础概念 1\. 什么是代理? 代理是一种通过中间服务器来帮助 访问目标服务器的技术。代理服务器位于客户端与服务器之间,充当两者的中介,从而实现客户端和服务器之间的隔离。用户的所有请求经过代理后,再发往目标服务器,而目标服务器的响应则返回代理,再由代理传递给用户。 2\. 网络代理的工作流程 在基本的网络代理工作流程中, 扮演了“请求转发者”和“响应返回者”的角色: 1. 客户端请求 :客户端将请求发送到代理服务器,而不是直接发...
学习面试
http-网络2024-11-29
没有koa的cors你怎么处理跨域?
关联问题: JSONP有何局限性 CORS如何处理复杂请求 代理在生产环境效果如何 前言 “金九银十”的秋招,就像是落进池塘的羽毛,连点水花都没砸起来。已读不回是常态,能给面试已是情分,能拿offer的更是少之又少。可怜我在寒潮来临的深秋之际,也只得哀叹一句“越来越冷了啊...” 不过人总是要吃饭的,所以再怎么冷,卖炭翁也得卖炭,牛马攻城狮也得“攻城”,既是为了填饱肚子,也是为了“春天”做准备。所以今天为各位前端工程狮细聊一下前端面试中...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录