跨域及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中的跨域 请求跨域有 ...
随机推荐
- xcode删除一个项目
退出xcode. 在Finder中删除项目文件夹.
- Gym 101470 题解
A:Banks 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt&q ...
- java中自定义注解的应用
要想深刻的理解注解,我们必须能实现自己的注解,然后应用自己的注解去实现特定的业务,使用注解可以更优雅的做到某些事情. 有这样一个场景,在需要文件导出时,我们需要将一个model中的一些重要字段导出到c ...
- Docker搭建disconf环境,三部曲之二:本地快速构建disconf镜像
Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...
- 【LeetCode】62-不同路径
题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为"Start" ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为& ...
- Dijkstra算法的Java实现
package main.java; import main.java.utils.GraphUtil; import java.util.ArrayDeque; import java.util.L ...
- [币严区块链]USDT钱包节点搭建
USDT是基于BTC发的稳定币,它是比特币的一条侧链,说简单点,就是在比特币区块数据的不可篡改性与区块唯一性的基础上,再封装了一层.具体原理可网上查资料.总之理解一点:USDT的钱包节点就是BTC的钱 ...
- 几道STL题目(FJUT - OJ STL训练1)
这个OJ一直在做,一些专题题目都很好,从易至难,阶梯上升,很适合像我这样的蒟蒻 =7= 这篇是关于其中一个专题训练的题解思路及代码 http://120.78.128.11/Contest.jsp ...
- 降低 80% 的读写响应延迟!我们测评了 etcd 3.4 新特性(内含读写发展史)
作者 | 陈洁(墨封) 阿里云开发工程师 导读:etcd 作为 K8s 集群中的存储组件,读写性能方面会受到很多压力,而 etcd 3.4 中的新特性将有效缓解压力,本文将从 etcd 数据读写机制 ...
- Java第二次作业第五题
自定义异常类,非法年龄类,并在person3类中使用此类,根据情况抛出异常,并进行处理. package naizi; class IllegalAgeException extends Except ...