前端怎么实现跨域请求

实现跨域请求,我们首先要先知道什么是跨域,紧接着便是跨域的方法,最后则是跨域时cookie的处理。

什么是跨域

1.什么是同源策略及其限制内容?

同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSSCSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制内容有:

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求发送后,结果被浏览器拦截了

但是有三个标签是允许跨域加载资源:

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

2.常见跨域场景

协议子域名主域名端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。

特别说明两点:

  • 第一:如果是协议和端口造成的跨域问题“前台”是无能为力的。
  • 第二:在跨域问题上,仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”。

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。

跨域有哪些方案?

1.CORS

CORS 通信过程都是浏览器自动完成,需要浏览器(都支持)和服务器都支持,所以关键在只要服务器支持,就可以跨域通信,CORS请求分两类,简单请求非简单请求

另外CORS请求默认不包含Cookie以及HTTP认证信息,如果需要包含Cookie,需要满足几个条件:

  • 服务器指定了 Access-Control-Allow-Credentials: true
  • 开发者须在请求中打开withCredentials属性: xhr.withCredentials = true
  • Access-Control-Allow-Origin 不要设为星号,指定明确的与请求网页一致的域名,这样就不会把其他域名的Cookie上传

简单请求

需要同时满足两个条件,就属于简单请求:

  • 请求方法是:HEAD、GET、POST,三者之一
  • 请求头信息不超过以下几个字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-Id
    • Content-Type:值为三者之一application/x-www/form/urlencodedmultipart/form-datatext/plain

需要这些条件是为了兼容表单,因为历史上表单一直可以跨域

浏览器直接发出CORS请求,具体来说就是在头信息中增加Origin字段,表示请求来源来自哪个域(协议+域名+端口),服务器根据这个值决定是否同意请求。如果同意,返回的响应会多出以下响应头信息

const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('收到数据:', xhr.responseText);}
};
xhr.open('GET', 'http://example.com/data.json', true);
xhr.send();
Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Credentials: true

在这个示例中,我们使用了 XMLHttpRequest 对象来进行跨域请求。我们设置了 withCredentials 属性为 true,表示允许跨域请求。同时,在服务器响应中需要设置以上响应头,其中 Access-Control-Allow-Origin 表示允许哪个域名下的请求,Access-Control-Allow-Credentials 表示是否允许发送凭证(如 cookie、HTTP 认证等)。

非简单请求

比如 PUT 或 DELETE 请求,或 Content-Type 为 application/json ,就是非简单请求。

非简单 CORS 请求,正式请求前会发一次 OPTIONS 类型的查询请求,称为预检请求,询问服务器是否支持网页所在域名的请求,以及可以使用哪些头信息字段。只有收到肯定的答复,才会发起正式XMLHttpRequest请求,否则报错

预检请求的方法是OPTIONS,它的头信息中有几个字段

  • Origin: 表示请求来自哪个域,这个字段是必须的
  • Access-Control-Request-Method:列出CORS请求会用到哪些HTTP方法,这个字段是必须的
  • Access-Control-Request-Headers: 指定CORS请求会额外发送的头信息字段,用逗号隔开

OPTIONS请求次数过多也会损耗性能,所以要尽量减少OPTIONS请求,可以让服务器在请求返回头部添加

Access-Control-Max-Age: Number // 数字 单位是秒

2.JSONP

JSONP 是一种常见的跨域请求方法。它是通过在 HTML 页面中添加一个 script 标签,来请求一个位于其他域名下的 JavaScript 文件。该 JavaScript 文件返回的数据需要使用一个回调函数进行包装,以便在原始页面中可以接收到数据。

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>JSONP 示例</title></head><body><script>function jsonpCallback(data) {console.log('收到数据:', data);}const url = 'http://example.com/data.json?callback=jsonpCallback';const script = document.createElement('script');script.src = url;document.body.appendChild(script);</script></body>
</html>

在这个示例中,我们通过添加一个 script 标签来请求 http://example.com/data.json 这个地址下的数据。由于该地址存在跨域问题,我们指定了一个名为 jsonpCallback 的回调函数,并将回调函数名作为参数传递到了地址中。当服务器返回数据时,会自动调用回调函数并将数据作为参数传入。

3.代理

如果无法使用 JSONP 或 CORS,可以尝试使用代理服务器来转发请求。在前端中,可以向自己的服务器发送请求,然后让服务器代理请求其它域名下的资源,并将结果返回给前端。

const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('收到数据:', xhr.responseText);}
};
xhr.open('GET', '/proxy?url=http://example.com/data.json', true);
xhr.send();

在这个示例中,我们向自己的服务器发送了一个 GET 请求,并在请求地址中添加了一个名为 proxy 的参数。服务器接收到请求后会将该请求转发到 http://example.com/data.json 地址下,并将响应结果返回给前端。

4.WebSocket

WebSocket 是一种支持跨域请求的协议,它允许客户端和服务器之间建立一个双向的通信通道。通过 WebSocket 可以实现跨域传输数据。
因为WebSocket请求头信息中有Origin字段,表示请求源来自哪个域,服务器可以根据这个字段判断是否允许本次通信,如果在白名单内,就可以通信
客户端代码:

const socket = new WebSocket('ws://example.com/ws');
socket.onopen = function() {console.log('连接已建立');socket.send('你好,服务器!');
};
socket.onmessage = function(event) {console.log('收到消息:', event.data);
};
socket.onerror = function(event) {console.log('发生错误:', event);
};

在这个示例中,我们通过创建一个 WebSocket 对象来连接 ws://example.com/ws 这个地址下的 WebSocket 服务。当连接建立成功后,我们发送了一段消息给服务器。当服务器返回消息时,会自动触发 onmessage 事件,并将服务器发送的数据作为参数传入。

需要注意的是,在使用 WebSocket 进行跨域通信时,服务器必须显式地指定允许哪些源访问 WebSocket 服务。服务器需要在握手阶段返回一个 Upgrade 头部,并在该头部中指定 Origin 头部的值。以下是一个使用 Node.js 实现的 WebSocket 服务的示例代码:

const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function(ws) {console.log('连接已建立');ws.on('message', function(message) {console.log('收到消息:', message);ws.send('你好,客户端!');});
});

在这个示例中,我们使用了 ws 模块创建了一个 WebSocket 服务,并监听在 8080 端口上。当客户端连接成功后,会触发 connection 事件,并返回一个 WebSocket 对象 ws。当客户端发送消息时,会自动触发 message 事件,并将客户端发送的数据作为参数传入。在这个示例中,我们将收到的消息直接返回给客户端。

5.postMessage

postMessage 是一种在不同窗口或跨域框架之间进行通信的机制。它允许一个窗口向另一个窗口发送消息,无论这两个窗口是否同源。

使用 postMessage 进行通信时,需要提供目标窗口的引用,并通过调用 postMessage 方法发送消息。以下是一个示例:

// 发送消息
const targetWindow = window.opener; // 获取目标窗口的引用
const message = 'Hello, world!';
const targetOrigin = 'http://example.com'; // 目标窗口的源
targetWindow.postMessage(message, targetOrigin);// 接收消息
window.addEventListener('message', function(event) {if (event.origin === 'http://example.com') {const message = event.data;console.log('收到消息:', message);// 处理接收到的消息}
});

在这个示例中,首先获取了目标窗口的引用 targetWindow,然后通过调用 postMessage 方法向目标窗口发送消息。发送的消息可以是任意类型的数据,例如字符串、对象等。

在接收消息的窗口中,通过添加 message 事件监听器来监听消息的接收,然后通过 event.data 获取收到的消息内容。可以通过 event.origin 来验证消息来源的域,确保只接受来自指定域的消息。

需要注意的是,为了确保安全性,应该始终在 postMessage 中指定目标窗口的源,以防止恶意窗口的干扰。同时,在接收消息时,应该对消息来源进行验证,并仅处理来自可信任源的消息。

总结来说,postMessage 提供了一种安全的跨窗口通信机制,可以在不同窗口、跨域框架之间进行双向通信。

这里只介绍几种开发中用的比较多的,几乎用不到的比如:

  • document.domain + iframe:适用主域名相同,子域名不同的跨域场景
  • window.name + iframe:利用name值最长可以 2M ,并用不同页面或不同域名加载后依然存在的特性
  • location.hash + iframe:适用通过 C 页面来实现 A 页面与 B 页面通信的场景

跨域时 Cookie 要做何处理?

在跨域请求中,Cookie 的处理需要额外注意。默认情况下,跨域请求是不会携带 Cookie 的,这是出于安全考虑。

如果你想在跨域请求中携带 Cookie,有以下几种方法:

  1. CORS(跨域资源共享):在服务端设置响应头部,允许指定的源携带 Cookie。具体做法是,在服务器返回的响应头中添加 Access-Control-Allow-Credentials: true,表示允许携带凭证(如 Cookie);同时,需要指定允许访问的源,可以使用 Access-Control-Allow-Origin: http://yourdomain.com 来限制只允许特定域名的请求携带 Cookie。

  2. 代理:将跨域请求发送到自己的服务器上,然后再由自己的服务器转发请求,并将响应返回给前端。由于请求是在同源下发起的,因此可以携带 Cookie。前端将请求发送给自己的服务器,然后自己的服务器再将请求发送给目标服务器,并将目标服务器的响应返回给前端。

  3. 在 URL 中传递参数:可以将需要的信息以参数的形式附加在 URL 上,而不是通过 Cookie 传递。这样不会触发同源策略,也不会引起跨域问题。

需要注意的是,使用 Cookie 进行跨域请求时,还需要设置 XMLHttpRequest 对象的 withCredentials 属性为 true。例如:

const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'http://example.com/api', true);
xhr.send();

同时,在服务端也要对跨域请求进行相应的处理,以确保安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/184189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞书全新版本搭载AI智能伙伴,支持用户自选底层大模型!

原创 | 文 BFT机器人 近日&#xff0c;字节跳动旗下飞书正式发布“飞书智能伙伴”系列AI产品。此次新产品有专属、易协作、有知识、有记忆、更主动等特点。除此之外&#xff0c;“飞书智能伙伴”作为一个开放的AI服务框架&#xff0c;各企业可根据业务场景自主选择适合的底层大…

13:kotlin类和对象 -- 属性(Properties)

定义属性 类属性可使用var和val定义 class Address {var name: String "Holmes, Sherlock"var street: String "Baker"var city: String "London"var state: String? nullvar zip: String "123456" }属性使用 fun copyAddres…

lua_next

lua_pushnil(L);while(lua_next(L, -2)){// 栈状态&#xff1a;key : -2 value : -1// do something lua_pop(L, 1);} lua_next 先弹出一个值&#xff0c; 再放一对pair 到栈上&#xff0c; 参数 index 是表的位置 调用后&#xff1a; -1&#xff1a;value -2:key 因为会先…

力扣labuladong——一刷day59

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣549. 二叉树中最长的连续序列二、力扣1325. 删除给定值的叶子节点 前言 像求和、求高度这种基本的二叉树函数很容易写&#xff0c;有时候只要在它们的后…

一次解决套接字操作超时错误的过程

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 在windows客户端使用QTcpSocket连接一个ubuntu服务端程序&#xff0c;出现套接字操作超时的错误。开始感觉还莫名其妙的&#xff0c;因为之前连接都是好好…

pandas超出print限制时如何查看完整dataframe

当设置了 pd.set_option(display.max_rows, None)&#xff0c;我们期望能够打印出数据框的所有行。然而&#xff0c;在某些情况下&#xff0c;即使设置了该选项&#xff0c;仍然无法完全打印出所有行的内容。这是因为数据量可能超出了系统的内存或显示限制。 为了解决这个问题…

鸿蒙系统扫盲(三):鸿蒙开发用什么语言?

1.两种开发方向 我们常说鸿蒙开发&#xff0c;但是其实鸿蒙开发分为两个方向&#xff1a; 一个是系统级别的开发&#xff0c;比如驱动&#xff0c;内核和框架层的开发&#xff0c;这种开发以C/C为主 还有一个是应用级别的开发&#xff0c;在API7以及以下&#xff0c;还是支持…

2023年全国职业院校技能大赛“ 信息安全管理与评估” 测试题

一、 单选题 &#xff08; 每题 2 2 分 &#xff0c;共 共 5 35 题&#xff0c;共 共 0 70 分&#xff09; 1、( )是指在信息的采集、加工、存储、传播和利用的各个环节中&#xff0c;用来规 范期间产生的各种社会关系的道德意识、道德规范和道德行为的总和。 A、信息规范 …

vue分环境打包及案例代码

Vue分环境打包可以帮助我们针对不同的环境(如开发环境、测试环境、生产环境等)打包出不同的版本,以满足不同的需求。下面是一个简单的Vue分环境打包的示例代码: 安装cross-env: npm install --save-dev cross-env在项目的根目录下创建不同的环境配置文件,如test.env.js…

Codeforces Round 907 (Div. 2) (C 贪心 D套路? F dfs序+差分树状数组)

A&#xff1a; 这种操作题&#xff0c;每次先想这个操作有什么性质 对于2^0来说可以操作 第1位 对于2^1来说可以操作 第1-2位 对于2^2来说可以操作 第1-4位 &#xff08;第3位无法单独修改&#xff09; 对于2^3来说可以操作 第1-8位&#xff08;第5 6 7位无法单独修改&…

Java中的i++是原子操作吗?

我们都知道i分为三步进行&#xff0c;分别是1:取到当前i的值&#xff0c;2&#xff1a;&#xff0c;3&#xff1a;将最终结果赋值 因此我们可通过创建两个线程&#xff0c;对同一个变量count,一个线程对count进行递增操作&#xff0c;另一个线程对count进行递减操作。每个线程…

Redis的高可用模式

1. 什么是高可用&#xff1f; 高可用&#xff08;High Availability, HA&#xff09;是指在信息技术中确保系统、服务或应用程序在绝大多数时间内都是可操作和可访问的能力。这通常涉及以下几个关键方面&#xff1a; 最小化停机时间: 高可用系统的目标是减少因硬件故障、系统升…

英语二笔记

完型填空 20题/0.5分 总分10, 至少拿8分 阅读理解A 20题/2分 总分40 至少拿24分 阅读理解B 5题/2分 总分10 至少拿6分 短文翻译 1题/15分 总分15分 至少拿9分 小作文 1题/10分 总分10分 至少拿6分 大作文 …

Talk | UCSB博士生许闻达:细粒度可解释评估初探

本期为TechBeat人工智能社区第551期线上Talk。 北京时间11月29日(周三)20:00&#xff0c;UC Santa Barbara博士生—许闻达的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “细粒度可解释评估初探”&#xff0c;分享了他们团队在具备解释性的细粒度…

流程不会搭建?集简云上线AI智能创建流程功能,辅助您更简单地创建自动化流程

用户在使用集简云创建流程时&#xff0c;经常会遇到的两个问题&#xff1a; 1. 不知道要如何选择应用动作&#xff0c;和动作的执行顺序&#xff1b; 2. 应用动作设置中的字段匹配&#xff0c;不知道要如何选择对应的字段&#xff1b; 集简云基于大量历史数据积累与自训练AI模…

BatchOutput PDF for Mac(PDF 批量处理软件)

BatchOutput PDF是一款适用于 Mac 的 PDF 批量处理软件。它可以帮助用户将多个 PDF 文件进行异步处理&#xff0c;提高工作效率。 BatchOutput PDF 可以自动化执行许多任务&#xff0c;包括 PDF 文件的打印、转换、分割、压缩、加密、重命名等&#xff0c;而且它还可以将自定义…

php许愿墙代码包括前端和后端部分

以下是一个简单的PHP许愿墙代码示例&#xff0c;包括前端和后端部分&#xff1a; 前端HTML代码&#xff08;index.html&#xff09;&#xff1a; <!DOCTYPE html> <html> <head><title>许愿墙</title> </head> <body><h1>许…

通过流量监控分析某个部门或客户端网络性能

在当今数字化时代&#xff0c;网络已经成为组织和企业不可或缺的基础设施之一。作为信息传输和数据交互的关键载体&#xff0c;网络的性能对于保障业务的稳定运行和提升工作效率至关重要。因此&#xff0c;对某个部门或客户端网络的性能进行分析和评估&#xff0c;有助于了解当…

MGF4964BL-01 低噪声 InGaAs HEMT(高电子迁移率晶体管) K波段放大器 微X型塑料封装

MGF4964BL-01超低噪声 InGaAs HEMT(高电子迁移率晶体管)设计用于K波段放大器。MGF4964BL-01是符合 RoHS 标准的产品&#xff0c;通过无铅认证。 MGF4964BL-01特征&#xff1a; f20GHz NFmin 时的低噪声系数。0.65 分贝(典型值) f20GHz 时的高相关增益 Gs 13.5dB(典型值。) MG…

spring cloud Eureka注册中心和Nacos注册中心

文章目录 Eureka注册中心.Eureka的结构和作用搭建eureka-server创建 服务引入eureka依赖编写启动类编写配置文件启动服务 服务注册1&#xff09;引入依赖2&#xff09;配置文件3&#xff09;启动多个user-service实例 服务发现1&#xff09;引入依赖2&#xff09;配置文件3&…