跨域及JSONP原理
什么是跨域:a.com 域名下的js无法操作b.com或是c.a.com域名下的对象
为什么浏览器要引入跨域问题?
跨域问题来源于浏览器的同源策略,为啥要有这个策略呢?
为了安全。假设现在有a.com 和b.com 两个域,如果没有同源策略的限制,那么a.com就可以随随便便就去b.com 里面拿东西,甚至一些cookie信息(常用于存储登录信息),那么a.com只需要一段代码就可以获取你的cookie信息,从而冒充你的身份去登录网站。
当使用 AJAX 跨域访问资源 会受到同源策略影响,浏览器会报错。
啥算跨域?
页面本身都有协议,域名,端口。当协议,域名,端口这三个有任意一个不一样就算跨域。
这里的跨域访问资源是那些资源呢(只有访问这些资源时浏览器不会显示给我们)?
- 后端接口的数据
- 其他域的cookie
- 其他域的缓存
当访问在有src属性的,或者部分href属性的,即使跨域浏览器也会返回给我们。只有跨域访问上面的资源浏览器才会报错。
事实上跨域是可以发出请求,浏览器也是可以接受到返回给我们的信息。但接受到数据之后发现页面的域和请求的域不同,所以判定跨域,不会把结果传递给我们的代码。也就是说同源策略是浏览器的一个安全策略。
那当有需要去访问别人服务器接口等这样的需求时,怎样解决同源策略的这种限制也就是跨域问题。
有人会不理解为啥浏览器地址栏直接访问接口不是跨域,而AJAX访问接口就是跨域问题。
你的AJAX所在的所在的位置是一个域,而访问的服务器接口是一个域。那在地址栏里是在客户端向往服务器里发型请求只存在服务端一个域。例如:你打开一个地址可以说就是请求了一个域的内容,http://www.baidu.com/xxx,你可以理解为www.baidu.com,就是一个域,这个时候你在这个地址内发出一个请求http://www.baidukuayu.com/xxx,那请求的就是www.baidukuayu.com.这两个地址的主域不一样可以为第二个请求跨域了。
在说一下为啥本地文件访问服务器也会出现跨域
因为本地文件(file:///C:/Users/master/Desktop/canvas/变换.html)前面的file也是个协议,是用来浏览器打开本地文件使用的文件协议。这也就解释了为啥会跨域因为协议不同嘛。而大多数网络相关的请求都是http或者https协议,所以无法进行与网络相关的操作(跨域,ajax,访问cookie等)
so,我们想办法绕过这个file协议,基本上每个编辑器都提供了插件,他在你本地代码启动的时候,可以隐式的返回一个服务。 例如在vscode的live server插件,webStrom 直接点击走上角的小浏览器标识就可以隐式的打开一个服务。
解决跨域问题
- 后端配合我们进行跨域
- JSONP
- 后端设置Access-Control-Allow-Origin属性支持跨域(让服务器告诉浏览器我这个接口所有网站都可以访问)
- 后端不配合我们进行跨域
- iframe(只能显示,不能控制)
- 通过服务器代理中转(原理:跨域只是浏览器的限制,但是我自己的服务器可以去访问被人的接口,我们访问自己的服务器,让自己的服务器去访问别人的接口,然后返回的数据再返回给服务器)
使用jquery JSONP跨域
$.ajax({
url:"", //请求地址
type:"", //请求方式
data:"", //要发送给服务器的值
dataType:"jsonp",//要求服务器返回的数据类型
async:"", //请求是否异步
success:function(data){ //成功的回调函数
......
}
})
成功跨域请求数据
我们发现发送请求的地址后面自动加上一个callback参数,而请求回来的jsonp数据的格式正是发送时的callback(json).
JSONP原理:动态创建script标签,使用script的src进行跨域
具体步骤:
- 判断请求的与当前页面域是否同源,如果同源正常发送ajax,如果不同源,生成一个script标签
- 生成一个随机的callback名字,并生成对应名字的方法。
- 设置script的src为要请求的接口,将callback参数拼接在后面。
- 后端接收到请求后,开始准备要返回的数据
- 后端拼接数据,将要返回的数据用callback包裹起来,将内容返回。
- 浏览区接收到内容那个,会当做js代码来执行。
- 从而执行第二步生成的方法,这样就接收到后端返回给我们的对象。
- jsonp选script的src进行跨域的原因?
我们知道带有src属性和部分的href属性是可以跨域的。但是href大多是样式。我们使用带src属性的。带src属性的有audio,video,img ,src,script等,但只有script是可以对数据进行控制,显示等。所以跨域的本质是使用script标签发出请求。例如引入jQuery的cdn: <script src = https://cdn.bootcss.com/jquery/3.4.1/jquery.js></script>
- 为什么jsonp都是使用get方式请求?
由于jsonp的原理就是使用script标签进行跨域,而script都是使用get方式请求数据。所以jsonp跨域只能是get方法,即使你设置的post方法,jQuery也会自动转为get方法。但如果你使用jsonp的方式并么有跨域,也就是同源,那么设置的get就是get,post还是post.
- 使用script便签索然可以引用其他域的资源,浏览器也不会限制,但是,浏览器会将但会的内容,作为代码执行。例如jQuery的cdn返回给我们的是jQuery源码
- jsonp为什么使用回调函数的方式处理返回的数据,以及为什么script的src后面为啥拼接一个callback参数呢?
在使用jsonp返回数据时,可能是个对象,也可能是个数组,但无论是什么都要给这个对象或数组附上一个名字(引用)以便访问这个数据,例如var a = {name:'zhang'},否则让我们怎么使用这个数据。
var script = document.createElement('script');
script.src = "./another.js";
document.body.appendChild(script);
console.log(a);
--another.js文件内容。--
var a = {name:'f'} //假设后端返回的数据
由于动态创建的script是异步加载的。所以访问a为被定义。
这时候我们就想到回调函数了,等js文件加好了,自动执行岂不是更好,并且还隐藏了返回数据的引用。
var script = document.createElement('script');
script.src = "./another.js";
document.body.appendChild(script);
function aa(data){
console.log(data);
}
--another.js文件内容。--
aa({name:'dg'}) //假设后端返回的数据
像这样创建一个函数,返回的数据用上面定义的函数名包裹执行这个已经定义好的函数,并把要返回的数据作为参数传递给要执行的函数。等到js文件加载完自动执行这个函数。
那怎样让后端知道你前端定义好的那个函数名(名字要一致啊,不然怎么执行),这是我们就知道了为啥url后面跟着一个callback参数了。直接把你定义好的函数名拼接在你要访问地址的后面一块传给后端岂不快哉。
- 默认是在url后加callback,如果想自定义函数的参数名取代默认的callback,可以通过使用$.ajax的jsonp参数
- jsonp原理代码实现
var $ = {
ajax : function (options) {
var url = options.url;
var type = options.type;
var dataType = options.dataType;
// 判断是否同源(协议,域名,端口是否相同)
var targetProtocol = ""; //目标接口协议
var targetHost = "" //目标接口的host(包括协议和端口)
// 如果url不带http,访问的就是相对路径(同源)
if (url.indexOf("http://") == 0 || url.indexOf("https://") == 0) {
var targetUrl = new URL(url);
targetProtocol = targetUrl.protocol;
targetHost = targetUrl.host;
} else {
targetProtocol = location.protocol;
targetHost = location.host;
}
// 判断是否是jsonp,如果不是jsonp,直接发送ajax
if (dataType == "jsonp") {
if (location.protocol == targetProtocol && location.host == targetHost) {
// 使用ajax
}
else { //跨域
// 随机生成一个callback,并生成对应的方法
var callback = "cb" + Math.floor(Math.random() * 1000000);
window[callback] = options.success;
// 创建script标签
var script = document.createElement('script');
// 如果url没有参数
if (url.indexOf('?') != -1) {
script.src = url + "&callback=" + callback;
}
else {//有参数
script.src = url + "?callback=" + callback;
}
// 将script添加到文档中
document.body.appendChild(script);
}
}
}
}
跨域及JSONP原理的更多相关文章
- Ajax跨域:Jsonp原理解析
推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...
- JQuery实现Ajax跨域访问--Jsonp原理
JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略).这一策略对于Java ...
- 跨域篇--JSONP原理
一篇文章让你明白 jsonp原理详解 什么是JSONP? 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自 ...
- JS跨域方法及原理
JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...
- Java跨域以及实现原理
最近研究了一下跨域,没接触之前我的印象就是配合单点登录的一种方式,后来在网上看到资料才知道不仅仅是这一种,用法很多,具体的可以去网上搜索. 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访 ...
- jQuery(三) javascript跨域问题(JSONP解决)
加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...
- 【原】Java跨域以及实现原理
前言:最近研究了一下跨域,主要是jsonp的实现,经过测试后总结如下: 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨 ...
- jquery跨域解决方案JSONP
1.在互联网中我们的计算机是通过IP来定位的,但是IP比较难记忆,因此通过domain name(域名)来取代IP 2.什么是跨域? (1)默认浏览器为了安全问题,禁止了xmlhttprequest跨 ...
- JS跨域:jsonp、跨域资源共享、iframe+window.name
JS跨域:jsonp.跨域资源共享.iframe+window.name :https://www.cnblogs.com/doudoublog/p/8652213.html JS中的跨域 请求跨域有 ...
随机推荐
- 五月月赛 寻宝 exkmp + 主席树
: 寻宝 时间限制: Sec 内存限制: MB 提交: 解决: [提交] [状态] [讨论版] [命题人:admin] 题目描述 采蘑菇的小西佬找到了一张上古年间的藏宝图,上面画着m座连绵不断的山,他 ...
- MySQL连接方式小结
1. 连接方式 1.1 方式1 /usr/local/mysql5./bin/mysql -p 此方法默认采用root@localhost用户登录, 1.2 方式2 /usr/local/my ...
- SVN更新失败
一.svn更新失败 使用svn遇到的问题是,更新失败,代码被锁定. 解决办法: 在项目上右键,如图所示: 图一: 图二: 之后再更新,基本上都没有问题了.如果还有问题,看下面. 二.工具清理 ...
- spring组件注册
基于注解和类的组件注册 @Conditional 作用:按照一定的条件进行判断,如果满足条件的话就给spring容器中注册bean 该注解既可以标注到方法上面,也可以标注到类上面(只有满足条件时, ...
- 【Offer】[41] 【数据流中的中位数】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值, ...
- Python Flask打造一个视频网站实战视频教程
下载链接:https://www.yinxiangit.com/607.html 目录: 本套课程从零基础讲解flask开发网站.涉及到的知识点包括:Python和pycharm的安装.urls和视图 ...
- Nginx安装及详解
Nginx简介: Nginx(发音engine x)专为性能优化而开发的开源软件,是HTTP.反向代理.邮件代理.TCP/UDP协议代理软件,由俄罗斯的作者Igor Sysoev开发,其最知名的优点是 ...
- SSM相关面试题(简答)
1.springmvc的执行 流程: 2.mybstis的执行流程: 3.ioc和DI的理解: 4.对aop的理解: 5.spring中常见的设计模式: 6.spring中声明式事务处理的配置: ...
- Winform中实现更改DevExpress的RadioGroup的选项时更改其他控件(TextEdit、ColorPickEdit)的值
场景 Winform中实现读取xml配置文件并动态配置ZedGraph的RadioGroup的选项: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article ...
- 1、单链表的实现(java代码)
1.创建链结构实体Node /** * 链表结构实体类 */ public class Node { Node next = null; //下一节点 int data; //节点数据 public ...