JavaScript中跨域问题的深入理解


Posted in Javascript onMarch 04, 2021

前言:

学习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属性引入文件的时候,无论是什么文件类型,都会被解析成一段字符串,然后当做js代码执行.于是就可以使用这个巧妙的方法来实现跨域请求了,下面看案例.

假设我这里有一个a.text文件里面有一句代码

alert('a')

JavaScript中跨域问题的深入理解

我们去另一个网页引用这个a.text这个文件

JavaScript中跨域问题的深入理解

页面一打开,弹出了a ,说明a.text文件中的代码被执行了

JavaScript中跨域问题的深入理解

正是这样,我们是设想 假如我们请求的是服务器上的的文件呢,也不需要考虑它是什么后缀的,只要有返回值给我就行,那我在前端就可以拿到.于是,开始操作!

当我们去请求另一台服务器的数据时,比如!

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>

此时浏览器会报错如下错误,也就是触发了同源策略,出现了跨域请求

JavaScript中跨域问题的深入理解


此时我们就可以用到上面说到的script标签上的src属性,我们使用script去请求服务器上的文件

此时我们只要在json.html文件上写一行代码

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

可以看到浏览器没有报错,请求到了文件,并且拿到了内容,那么问题来了,我们怎么去拿到返回的结果呢?

这里就可以巧妙的运用一下回调函数.

JavaScript中跨域问题的深入理解

后端返回数据可以使用调用函数的方式来执行.

1.php文件后端的代码为

<?php

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

?>

jsop.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文件,在1.php文件就可以拿到这个,fn函数,调用传入讲到返回的数据,这样就可以在前端通过函数调用的方式轻松拿到.

也就是说我们在前端定义了一个全局函数,名为 fn 记住,一定是全局的函数, 函数名就是指向该函数的指针, 把函数名传过去, 后端拿到了,进行一番操作后 返回的是fn(‘sanqian'),而这个结果就会被拿到前端,当做js代码执行.也就说上面的代码等价于下面的代码

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

这样一来就是上面定义,下面执行调用,如此一来,就拿到了后端返回的结果.

JavaScript中跨域问题的深入理解

jsonp就是这么一个原理和使用方法,目前使用也是较为广泛的.要会的喔!

方法二: CROS

这是一个纯后端的方法,和前端没有任何关系.

当我们就真的傻乎乎去另一台服务器上请求数据的时候,浏览器就会有个经典的报错如下:

JavaScript中跨域问题的深入理解

翻译一下就是

JavaScript中跨域问题的深入理解

也就是访问被干掉了,我们需要吧请求的资源放在Access-Control-Allow-Origin标头上,

那么同样要返回结果[sanqian] , 然后我们的前后端代码就变成了下面这样

jsonp.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的需要花钱

nginxhttp和https都是免费的,所以使用nginx代理,也用nginx演示

我们首先需要在nginx服务器上配置好路径

JavaScript中跨域问题的深入理解

在配置文件的

servr{}里面

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

JavaScript中跨域问题的深入理解

配置好之后,jsonp.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中跨域问题的文章就介绍到这了,更多相关JavaScript跨域问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js 全兼容可高亮二级缓冲折叠菜单
Jun 04 Javascript
jQuery事件 delegate()使用方法介绍
Oct 30 Javascript
open 动态修改img的onclick事件示例代码
Nov 13 Javascript
基于jQuery.Hz2Py.js插件实现的汉字转拼音特效
May 07 Javascript
AngularJS 使用$sce控制代码安全检查
Jan 05 Javascript
Bootstrap+jfinal退出系统弹出确认框的实现方法
May 30 Javascript
BootStrap智能表单实战系列(四)表单布局介绍
Jun 13 Javascript
概述如何实现一个简单的浏览器端js模块加载器
Dec 07 Javascript
JQueryMiniUI按照时间进行查询的实现方法
Jun 07 jQuery
VuePress 中如何增加用户登录功能
Nov 29 Javascript
JS前后端实现身份证号验证代码解析
Jul 23 Javascript
vue-cli单页面预渲染seo-prerender-spa-plugin操作
Aug 10 Javascript
vue3.0中使用element的完整步骤
Mar 04 #Vue.js
jQuery实现鼠标拖动图片功能
Mar 04 #jQuery
ajax jquery实现页面某一个div的刷新效果
Mar 04 #jQuery
jquery实现广告上下滚动效果
Mar 04 #jQuery
VUE实现吸底按钮
Mar 04 #Vue.js
vue实现可移动的悬浮按钮
Mar 04 #Vue.js
vue中axios封装使用的完整教程
Mar 03 #Vue.js
You might like
PHP脚本的10个技巧(2)
2006/10/09 PHP
PHP读取目录下所有文件的代码
2008/01/07 PHP
php 文件上传代码(限制jpg文件)
2010/01/05 PHP
在WINDOWS中设置计划任务执行PHP文件的方法
2011/12/19 PHP
CMS中PHP判断系统是否已经安装的方法示例
2014/07/26 PHP
php实现的返回数据格式化类实例
2014/09/22 PHP
php查询相似度最高的字符串的方法
2015/03/12 PHP
ThinkPHP框架整合微信支付之刷卡模式图文详解
2019/04/10 PHP
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
javascript高亮效果的二种实现方法
2008/09/14 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
js面向对象之静态方法和静态属性实例分析
2015/01/10 Javascript
Bootstrap学习笔记之css样式设计(2)
2016/06/07 Javascript
详解BootStrap中Affix控件的使用及保持布局的美观的方法
2016/07/08 Javascript
JS封装的选项卡TAB切换效果示例
2016/09/20 Javascript
javascript 显示全局变量与隐式全局变量的区别
2017/02/09 Javascript
浅谈$_FILES数组为空的原因
2017/02/16 Javascript
JavaScript使用链式方法封装jQuery中CSS()方法示例
2017/04/07 jQuery
jQuery Validate 无法验证 chosen-select元素的解决方法
2017/05/17 jQuery
分享vue里swiper的一些坑
2018/08/30 Javascript
webpack的CSS加载器的使用
2018/09/11 Javascript
vue下拉菜单组件(含搜索)的实现代码
2018/11/25 Javascript
微信小程序登录数据解密及状态维持实例详解
2019/05/06 Javascript
Python程序员开发中常犯的10个错误
2014/07/07 Python
Python 搭建Web站点之Web服务器与Web框架
2016/11/06 Python
Python判断文件或文件夹是否存在的三种方法
2017/07/27 Python
python TKinter获取文本框内容的方法
2018/10/11 Python
pytorch判断是否cuda 判断变量类型方式
2020/06/23 Python
详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据
2020/12/13 Python
日本航空官方网站:JAL
2019/06/19 全球购物
杭州SQL浙江浙大网新恩普软件有限公司
2013/07/27 面试题
2014高考励志标语
2014/06/05 职场文书
社团活动总结书
2014/06/27 职场文书
汉语言文学毕业求职信
2014/07/17 职场文书
七夕活动策划方案
2014/08/16 职场文书
师德师风个人整改措施
2014/10/27 职场文书