2020-01-18
跨域访问资源
什么东西属于资源?
js文件算吗?算,但是js文件是允许被跨域请求的。所有的src请求的资源可以被跨域请求。href大部分可以被跨域请求。css文件jpg文件等。
哪资源算跨域请求的资源?
1.后端接口的数据。
2.其他域的Cookie。
3.其他域的缓存。
什么是其他的域?怎么样算跨域?
页面本身:有协议(http/https),域名,端口
要请求的数据:https://www.baidu.com:80
协议域名端口号这三个有任意一个不一样就算跨域。
--------------------------------------kk---------------------------------------------------------------------
跨域这个行为发生在哪里?
1.即使跨域了(协议,域名,端口号有不一样的),请求也可以发出。
2.服务器端也可以接收
3.服务器端也可以正常处理
4.服务器端也是可以正常返回数据的
5.浏览器端也可以接收到这些数据。
6.接收到之后,当发现页面和域的请求不同,所以判定为跨域。
7.我们的代码在这等着结果呢,但是因为浏览器判定跨域了,不会把结果传递给我们的代码。
------------------------------------------------kk--------------------------------------------------------
解决跨域的方法
1.后端配合我们跨域
pan.baidu.com -->zhidao.baidu,com
(1)JSONP(正常情况下,返回的数据都是JSON格式,JSONP是一种特殊的格式)
(2)后端设置Access-Control-Allow-Origin属性以支持跨域。
2.后端不配合我们进行跨域。
(3)iframe(只能显示,不能控制)
(4)通过后端代理(自己的后端)
//原生发送Ajax
<script>
var xhr = null;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Miscrosoft.XMLHttp");
}
console.log(xhr.readyState);//0
xhr.open("get","http://developer.duyiedu.com/edu/testAjaxCrossOrigin");
console.log(xhr.readyState);//1
xhr.onreadystatechange = function(){
//readystate == 4表示请求完成,已经接收到数据。
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}
xhr.send();
</script>
<script>
$.ajax({
url:"http://developer.duyiedu.com/edu/testJsonp",
type:"get",
dataType:"jsonp",
success:function(data){
console.log(data);
}
});
// jsonp跨域,只能使用get方法,如果我们设置的时post方法,jquery会在动转为get方法。
// 是不是在jsonp里面只能使用get方法?是不是我设置的post方法都会转为get方法?
//不是,jquery会先判断是否同源,如果同源,设置什么是什么。如果不同源,都为get
</script>
---------------kk-------------------------------------------------------------------------------
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
同源
域名、协议、端口相同,也就是在同一个域里。
非同源受到的限制
cookie不能读取 (如我在自己的站点无法读取博客园用户的cookie)
dom无法获得
ajax请求不能发送
-----------------------kk---------------------------------------------------------------------------
因为我想从一个接口中获取一个数据
但是这个接口和当前页面不是同源的。(跨域)
但是这个借口是支持JSONP的
script标签,有src属性,可以发送网络请求
script标签,虽然可以引用其他返回内容,浏览器不限制。
但是,浏览器会将返回的内容作为js代码执行。
JSONP原理:
1.判断请求与当前页面的域是否同源,同源发送正常ajax
2.如果不同源会生成一个script标签
3. 生成一个随机的callback,创建一个名为这个的方法
4.设置script标签的src,设置请求的接口
5.将callback作为参数拼接在后面
---------------------------------以上是前端部分----------------------------------------------
6.后端接收到请求后,开始准备要返回的数据
7.后端拼接数据,将要返回的数据用callback的值和括号包裹起来
例如callback = asd123456,要返回的数据为{“a”:1,“b”:2 }
就要拼接为 asd123456({“a”:1,“b”:2 });
8.将内容返回
-----------------------------------以上是后端部分----------------------------------------
9.浏览器接收到内容,会当做js代码来执行
10.从而执行名为asd123456的方法,这样我们就接收到了后端返回给我们的对象。
<script>
var $ = {
ajax:function(options){
var url = option.url;
var type = options.type;
var dataType = option.dataType;
// 判断是否同源(协议,域名,端口号)
// 获取目标url的域
var targetProtocal = "";//目标接口的协议
var targetHost = "";//目标端口的host,host包含域名和端口;
// 如果url不带http,name访问的是相对路径,相对路径一定是同源的
if(url.indexOf("http://") == 0 ||url.indexOf("https://") == 0 ){
var targetUrl = new URL(url);
targetProtocal = targetUrl.protocol;
targetHost = targetUrl.host;
}else{
targetProtocal = location.protocol;
targetHost = location.host;
}
// 首先判断是否为jsonp,因为不是jsonp直接发送ajax就行。
if(dataType == "jsonp"){
// 看是否同源
if(location.protocol == targetProtocal && location.host ==targetHost){
// 同源当做普通ajax做请求
}else{
// 随机生成一个callback
var callback = "cb" + Math.floor(Math.random() * 1000);
// 给window上添加一个方法
window[callback] = option.success;
// 生成script标签。
var script = document.createElement("script");
if(url.indexOf("?") > 0){//表示已经有参数了
script.src = url + "&callback" + callback;
}else{//没有参数
script.src = url + "?callback=" + callback;
}
script.id = callback;
document.head.appendChild(script);
}
}
}
}
$.ajax({
url:"http://developer.duyiedu.com/edu/testJsonp",
type:"get",
dataType:"jsonp",
success:function(data){
console.log(data);
}
});
</script>