JSONP_跨域

题目1: 什么是同源策略

  • 同源策略(Same Origin Policy): 浏览器出于安全方面的考虑, 只允许与本域下的接口交互. 不同源的客户端脚本在没有明确授权的情况下, 不能读写对方的资源.
  • 本域指同域名同协议同端口,即URL完全相同
  • 注意: 对于当前页面来说页面存放的Js文件不重要, 重要的是加载该js页面所在什么域

题目2: 什么是跨域?跨域有几种实现形式

  • 跨域: 利用JS在不同域进行数据的传输或通信, 例如用ajax向一个不同的域请求数据, 或者通过JS获取页面中不同域的iframe中的数据
  • 实现形式:
    1. JSONP: 利用引入JS文件不受同源策略限制的特性, 前后端配合实现跨域访问接口
    2. CORS: W3C标准中的一个, 允许跨域发出xmlhttprequest请求, 需要服务端配合实现
    3. 降域: 修改document.domain, 将其设置为更高一级的父域, 从而符合同源策略
    4. postMessage
    5. NGINX代理
    6. node.js中间件
    7. webSocke协议跨域

题目3: JSONP 的原理是什么
JSONP就是通过script标签加载数据的方式去获取数据当做JS代码来执行; 提前在页面上声明一个函数, 函数名通过接口传参的方式传给后台, 后台解析到函数名后在原始数据上包裹这个函数名, 发送给前端
题目4: CORS是什么

  • CORS(Cross-Origin Resource Sharing) 跨域资源共享, 是一种ajax跨域请求资源的方式, 支持现代浏览器,IE10以上
  • 实现方式: 当使用XMLHTTPRequest发送请求上, 浏览器发现该请求不符合同源策略, 会给该请求加上一个请求头: Origin, 后台进行一系列处理, 如果确定接收请求则在返回结果中加一个响应头: Access-Control-Allow-Origin; 浏览器判断该响应头中是否包含Origin的值, 如果有则浏览器处理响应, 我们可以拿到响应数据, 如果不包含浏览器直接驳回, 这时我们无法拿到响应数据
  • CORS表象让人感觉他与同源ajax请求没啥区别, 代码完全一样

浏览器将CORS请求分为两类:简单请求和非简单请求
只要同时满足下面两大条件,就属于简单请求

  1. 请求方法是以下三种方法之一:
    HEAD
    GET
    POST
  2. HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
    不能同时满足上面2个条件的,就属于非间请求
    比如对server端有特殊要求的请求,请求方法是PUT或者DELETE、content-type字段类型是application/json的

题目5: 根据视频里的讲解演示三种以上跨域的解决方式 ,写成博客

  1. JSONP
    通常为了减轻web服务器的负载, 我们把js, css, img等静态资源分离到另一台独立域名的服务器上,在HTML页面中再通过相应的标签从不同域名下加载静态资源, 而浏览器允许, 基于此原理, 我们可以通过动态创建script, 再请求一个带参网址实现跨域通信.

    1. 原生实现
    var script = document.creatElement('script');
    script.type = 'text/javascript';
    script.src = 'http://www.domain2.com:8080/login?            user=admin&callback=onBack';
    document.body.appendChild(script);
    function onBack(res){
      alert(JSON.stringify(res));
    }
    服务器返回
    onBack({"status":true, "user":"admin"})
    
    1. jquery ajax:
    $.ajax({
      url:'http://www.domain2.com:8080/login',
      type:'get',
      dataType:'jsonp',// 请求方式为jsonp
      jsonpCallback:"onBack",// 自定义回调函数名
      data:{}
    });
    

后端node.js代码示例:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request',function(req,res){
varparams = qs.parse(req.url.split('?')[1]);
var fn = params.callback;
// jsonp返回设置
res.writeHead(200,{'Content-Type':'text/javascript'});
res.write(fn+'('+JSON.stringify(params)+')');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');

jsonp缺点:只能实现get一种请求。
  1. 降域
    此方案仅限主域相同, 子域不同的跨域应用场景.
    实现原理: 两个页面都通过js强制设置document.domain为基础主域, 就实现了同域.
1. 父窗口: (http://www.domain.com/a.html)
document.domain = 'domain.com'
var user = 'admin'
2. 子窗口: (http://child.domain.com/b.html)
document.domain = 'domain.com'
alert('get js data from parent' + window.parent.user)
// 获取父窗口中变量
  1. location.hash + iframe跨域
    实现原理: a域与b域相互通信, 通过中间页c来实现. 三个页面, 不同域之间利用iframe的location.hash传值, 相同域之间直接js访问来通信
    具体实现: a域: a.html > b域: b.html > a域: c.html , ab不同域只能通过hash值单向通信, bc也不同域只能单向通信, 但ac同域, 所以c可通过parent.parent访问a页面所有对象
1. a.html: (http://www.domain1.com/a.html)
var iframe = document.getElementById('iframe')
setTimeout(function(){
  iframe.src = iframe.src + '#user=admin'
}, 1000); // 向b.html传hash值
functionCallback(res){
  alert('data from c.html' + res)
}// 开放给同域c.html的回调方法
2. b.html: (http://www.domain2.com/b.html)
var iframe = document.getElementById('iframe');
window.onhashchange = function(){
  iframe.src += location.hash;
}// 监听a.html传来的hash值,再传给c.html
3. c.html:(http://www.domain1.com/c.html)
window.onhashchange = function(){// 监听b.html传来的hash值
  window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=',''));
}
  1. postMessage
    postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
    a.) 页面和其打开的新窗口的数据传递
    b.) 多窗口之间消息传递
    c.) 页面与嵌套的iframe消息传递
    d.) 上面三个场景的跨域数据传递
    用法:postMessage(data,origin)方法接受两个参数
    data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
    origin: 协议+主机+端口号,也可以设置为”*”,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/”。
1. a.html:(http://www.domain1.com/a.html)
var iframe = document.getElementById('iframe');
iframe.onload = function(){
  var data = {name:'aym'};
   iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
}
window.addEventListener('message', function(e){
  alert('data form domain2 ' + e.data);
}, false);
2. b.html:(http://www.domain2.com/b.html)
window.addEventListener('message', function(e){
  alert('data from domain1 ' + e.data);
  var data = JSON.parse(e.data);
  if(data){
    data.number = 16;
    window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
  }
}, false);
  1. 跨域资源共享(CORS)
    普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置。
    带cookie请求:前后端都需要设置字段,另外需注意:所带cookie为跨域请求接口所在域的cookie,而非当前页。
    目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。
1. 前端设置:
ajax:
var xhr=newXMLHttpRequest();// IE8/9需用window.XDomainRequest兼容
xhr.withCredentials=true;// 前端设置是否带cookie
xhr.open('post','http://www.domain2.com:8080/login',true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange=function(){
  if(xhr.readyState==4&&xhr.status==200){
    alert(xhr.responseText);
  }
};
2. Nodejs后台示例:
var http=require('http');
var server=http.createServer();
var qs=require('querystring');
server.on('request',function(req,res){
  var postData='';
req.addListener('data',function(chunk){
  postData+=chunk;
});// 数据块接收中
req.addListener('end',function(){
  postData=qs.parse(postData);
// 跨域后台设置
  res.writeHead(200,{
  'Access-Control-Allow-Credentials':'true',// 后端允许发送Cookie
  'Access-Control-Allow-Origin':'http://www.domain1.com',// 允许访问的域(协议+域名+端口)
  'Set-Cookie':'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'// HttpOnly:脚本无法读取cookie
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080...');
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • 什么是同源策略 同源政策(same-origin policy)是指同域名(或ip),同端口,同协议视为同一个域,...
    小囧兔阅读 508评论 0 1
  • 1: 什么是同源策略 最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源",所谓...
    好奇而已阅读 300评论 0 0
  • 1.什么是同源策略浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不...
    24_Magic阅读 497评论 0 0
  • 什么是同源策略 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995...
    YQY_苑阅读 313评论 0 0
  • 爱情是个永恒的话题。之于爱情,每个人都有自己的感受。加西亚•马尔克斯在他的两部鸿篇巨制——《霍乱时期的爱情》和...
    巴山夜雨i阅读 838评论 7 4