一、为什么产生:
同源策略(域名,协议,端口),安全问题
二、怎么解决:
1、cros:修改响应头
2、+jp:采用js标签
3、+代理(创建服务器,定义规则,服务器与服务器之间不存在跨域问题)
当服务器提供解决方案时用前两种,不提供时用代理
跨域问题(Cross-Origin Resource Sharing, CORS)是前端开发中常见的问题,它发生在一个域的网页尝试访问另一个域的资源时。出于安全考虑,浏览器实施了同源策略(Same-Origin Policy),限制了来自不同源的文档或脚本间的交互。以下是几种常用的解决跨域问题的方法,每种方法都带有详细的步骤:
1. JSONP(JSON with Padding)
步骤:
- 创建一个回调函数:在前端页面定义一个回调函数,用于处理从服务器返回的数据。
- 发送请求:通过
<script>
标签发送请求到服务器,请求中包含回调函数的名称。 - 服务器处理:服务器接收到请求后,将数据包装在回调函数中返回。
- 浏览器执行:浏览器执行
<script>
标签中的脚本,触发回调函数,前端获取数据。
**优点:**兼容性好,几乎所有浏览器都支持。 **缺点:**只支持GET请求,安全性较低。
2. CORS(Cross-Origin Resource Sharing)
步骤:
- 发送预检请求(可选):浏览器先发送一个OPTIONS请求到服务器,询问是否可以进行实际请求。
- 服务器响应:服务器在响应中设置
Access-Control-Allow-Origin
等头部,允许跨域访问。 - 发送实际请求:浏览器根据预检请求的响应决定是否发送实际请求。
- 服务器处理并响应:服务器处理请求并返回数据。
**优点:**支持各种HTTP请求方法,安全性高。 **缺点:**需要服务器端配置,可能需要后端开发人员介入。
3. 代理服务器
步骤:
- 设置代理服务器:在服务器端设置一个代理服务,用于转发前端的请求到目标服务器。
- 前端请求代理:前端发送请求到代理服务器。
- 代理服务器转发:代理服务器将请求转发到目标服务器。
- 获取响应:代理服务器将目标服务器的响应转发回前端。
**优点:**可以绕过浏览器的同源策略,适用于复杂场景。 **缺点:**增加了系统的复杂性,可能影响性能。
4. 窗口消息传递(Window.postMessage)
步骤:
- 创建iframe:在主页面中创建一个指向第三方网站的
<iframe>
。 - 设置消息监听:在
<iframe>
和主页面中分别设置监听器,监听message
事件。 - 发送消息:通过
postMessage
方法在<iframe>
和主页面之间传递消息。
**优点:**可以实现跨源通信,不受限于同源策略。 **缺点:**需要第三方网站的配合,使用场景有限。
5. 文档域(document.domain)
步骤:
- 设置相同域:两个不同子域的页面设置相同的
document.domain
属性。 - 共享数据:通过共享的域进行数据交互。
**优点:**适用于有相同主域但不同子域的情况。 **缺点:**只适用于具有相同主域的两个不同子域之间。
6. Webpack Dev Server 代理
步骤:
- 配置Webpack Dev Server:在Webpack开发服务器配置中设置代理规则。
- 前端请求:前端通过Webpack Dev Server发起请求。
- 代理转发:Webpack Dev Server将请求转发到目标服务器。
**优点:**开发环境中方便使用,无需服务器端配置。 **缺点:**仅限于开发环境,生产环境需要其他方案。
每种方法都有其适用场景和限制,开发者需要根据实际情况选择最合适的解决方案。
面试:
得分点
同源限制、协议、域名、端口、CORS、node中间件、JSONP、postmessage
标准回答
跨域:当前页面中的某个接口请求的地址和当前页面的地址如果协议、域名、端口其中有一项不同,就说该接口跨域了。
跨域限制的原因:浏览器为了保证网页的安全,出的同源协议策略。
跨域报错信息:
跨域解决方案
cors:目前最常用的一种解决办法,通过设置后端允许跨域实现。
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader("Access-Control-Allow-Methods", "GET, PUT, OPTIONS, POST");
node中间件、nginx反向代理:跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理,都是让请求发给代理服务器,静态页面面和代理服务器是同源的,然后代理服务器再向后端服务器发请求,服务器和服务器之间不存在同源限制。
JSONP:利用的原理是script标签可以跨域请求资源,将回调函数作为参数拼接在url中。后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成javascript。
postmessage:H5新增API,通过发送和接收API实现跨域通信。
加分回答
跨域场景:前后端分离式开发、调用第三方接口