JavaScript跨域原理与三种常见解决方案详解

作者:闭包旅人时间:2026-10-24 08:35:37浏览:292

本文深入解析JavaScript中的跨域问题,阐述同源策略中协议、域名和端口号的判定规则。详细讲解JSONP利用script标签实现跨域的原理及回调函数机制,CORS后端Access-Control-Allow-Origin头配置方法,以及通过Nginx服务器代理解决跨域请求的完整流程。

前言

学习JavaScript的开发者都知道,当我们在浏览器地址栏输入网址并发送网络请求时,浏览器会自动跳转到对应页面。例如输入www.baidu.com,浏览器会跳转至百度首页。浏览器发送网络请求需要三个基本要素。

完整的URL路径实际上包含协议、域名和端口号。例如http://www.baidu.com:80,浏览器在发送请求时默认会补全协议(http)和端口号(80)。因此,完整的URL至少包含三个部分。

1. http/https 传输协议

2. www.baidu.com 域名

3.80 端口号

正是基于这三个基本要素,才产生了跨域请求的概念。所谓跨域,是指当传输协议、域名或端口号中任意一个或多个不相等时,就会触发浏览器的同源策略。同源策略要求三者完全一致,属于同一源头。

补充说明

- 同源策略由浏览器强制执行。

浏览器限制向其他服务器发送请求,仅允许向自身服务器发送请求。若尝试向其他服务器发送请求,浏览器会进行阻止。

- 什么是“其他服务器”?

当请求的协议、域名或端口号中任意一个存在差异时,即视为访问其他服务器,此时会触发同源策略。

既然浏览器阻止跨域请求(即限制访问其他服务器),我们需要寻找解决浏览器限制的方法,以实现跨域请求。

在实际案例中,跨域请求十分常见。例如,A网站需要引用B网站的图片资源,最佳方式是向B网站服务器请求这些图片。当A网站需要B网站的数据时,便形成了跨域请求。

**

如何实现跨域请求?

**

方法一:JSONP

在学习JSONP技术前,需了解一个机制:通过script标签的src属性引入文件时,无论文件类型如何,都会被解析为字符串并作为JavaScript代码执行。利用这一特性,可以实现跨域请求,具体案例如下。

假设有一个a.text文件,其中包含一行代码:


alert('a')

前言

我们在另一个网页中引用这个a.text文件。

前言

页面加载后弹出提示框显示“a”,说明a.text文件中的代码已成功执行。

前言

基于此原理,如果我们请求的是服务器上的文件,无需关心其后缀名,只要服务器返回数据,前端即可获取。接下来进行具体操作。

当我们请求另一台服务器的数据时,例如:

http://10.36.136.96:80/ 是目标服务器地址。

1.php 是目标服务器上的文件,我们尝试正常发起请求。

在目标服务器上存在一个名为1.php的文件。


 <script>
 //http://10.36.136.96:80/是另一台服务器的地址
 //1.php是另一台服务器上的文件,我们正常去请求

 var xhr = new XMLHttpRequest()
 xhr.open('get','http://10.36.136.96:80/1.php')
 xhr.onload = function () { 
 console.log(xhr.responseText);//1.php文件将要返回的结果
 }
 xhr.send()
 </script>

此时浏览器会报错,提示触发了同源策略,出现跨域请求错误。

前言


此时我们可以利用前文提到的script标签的src属性,通过script标签向服务器文件发起请求。

在json.html文件中添加一行代码:


 <script src="http://10.36.136.96:80/1.php"></script>

可以看到浏览器未报错,成功请求到文件并获取内容。但问题来了,如何获取返回的具体结果?

这里可以巧妙运用回调函数。

前言

后端返回数据时,可以通过调用函数的方式来执行。

1.php文件后端的代码如下:


<?php

 $_GET['callback'];
 echo "$name('sanqian')";

?>

json.html文件前端的代码如下:


<script>
 function fn(data){
  console.log(data);
 }
 </script>
 <script src="http://10.36.136.96:80/1.php?callback=fn"></script>

callback等号后面的值为回调函数名,将其传递给1.php文件。后端获取该函数名后,调用传入的数据并返回结果,从而在前端通过函数调用的方式轻松获取数据。

也就是说,我们在前端定义了一个名为fn的全局函数。注意,必须是全局函数,因为函数名指向该函数的指针。将函数名传递过去,后端执行操作后返回fn('sanqian'),该结果被前端作为JavaScript代码执行。上述代码等价于:


 <script>
 function fn(data){
  console.log(data);
 }
 </script>
 <script>
 fn('sanqian')
 </script>

这样便实现了先定义后执行调用的过程,从而成功获取后端返回的结果。

前言

JSONP的原理和使用方法如上,目前应用较为广泛,建议掌握。

方法二:CORS

这是一种纯后端实现的方法,与前端代码无关。

当我们直接向另一台服务器请求数据时,浏览器会报出经典错误:

前言

翻译过来即:

前言

访问被禁止。我们需要将请求的资源地址放入Access-Control-Allow-Origin响应头中。

若需返回结果[sanqian],前后端代码调整如下:

json.html文件代码:


 <script>
 var xhr = new XMLHttpRequest()
 xhr.open('get','http://10.36.136.96:80/1.php')
 xhr.onload = function () { 
  console.log(xhr.responseText);
  }
  xhr.send()

1.php文件代码:


<?php
 header('Access-Control-Allow-Origin:*');
 echo "sanqian";
?>

只需添加这一行代码,即可正常请求到目标资源。

当然,还可以配置更多代码,例如:


//表明允许跨域访问
header(Access-Control-Allow-Origin:上面origin的地址)//*号代表所有
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http 动作
header('Access-Control-Allow-Headers:x-requested-with,content-type'); //响应头 请按照自己需求添加

这是跨域请求中最简单的方法,且完全由后端处理。

方法三:服务器代理

Proxy(代理)

代理跨域(服务器正向代理跨域),因为浏览器不允许请求非同源地址。

在浏览器同源限制下,可以引入代理服务器:将本应发送给目标服务器的请求发送给代理服务器,由代理服务器转发请求给目标服务器,目标服务器将响应返回给代理服务器,最后由代理服务器将响应返回给浏览器。

任何服务器均可进行代理,但Apache代理HTTP无需费用,代理HTTPS需付费。

而Nginx对HTTP和HTTPS代理均免费,因此使用Nginx进行代理演示。

首先需要在Nginx服务器上配置好路径。

前言

在配置文件的

server{}块内


serve{
...
location = /sanqian {
	proxy_pass http://10.36.136.96:80/1.php;
	}
...
}

前言

配置完成后,json.html文件的代码变为:


 <script>
 var xhr = new XMLHttpRequest()
 xhr.open('get','/sanqian') // 注意这里变了
 xhr.onload = function () { 
  console.log(xhr.responseText);
  }
  xhr.send()
 </script>

1.php文件代码变为:


<?php 
 echo "sanqian";
?>

/sanqian 是本机服务器上的路径。当请求路径为/sanqian时,服务器识别出实际目标是访问http://10.36.136.96:80/1.php,代理服务器随后访问该地址,获取结果后返回给当前访问的浏览器,从而成功获取数据。

前言

以上是对跨域请求的简单理解,内容可能不全或有疏漏,欢迎指正,谢谢!

总结

至此,关于JavaScript中跨域问题的文章介绍完毕。更多相关JavaScript跨域问题内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章