跨域
2019-01-14 22:55 系佛 阅读(180) 评论(0) 编辑 收藏 举报跨域
一、同源策略
-
是浏览器的一个功能;
-
同源就是指协议、域名、端口号相同;
-
不同源的客户端脚本在没明确授权的情况下,不能读写对方的资源;
举例如下:在文件夹中定义两个文档sever.js和index.html
server.js
var http = require('http') var fs = require('fs') var path = require('path') var url = require('url') http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case '/getWeather': console.log("get weather"); res.end(JSON.stringify({beijing: 'sunny'})) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, 'not found') res.end('<h1>404 Not Found</h1>') }else{ res.end(data) } }) } }).listen(8080)
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello World</h1> <script> var xhr = new XMLHttpRequest() xhr.open('GET','http://localhost/getWeather', true) xhr.send() xhr.onload = function(){ console.log(xhr.responseText) } </script> </body> </html>
同样表示本机ip,但如果用localhost:8080打开/getWeather,则在页面显示天气信息,而如果用127.0.0.1打开则不能。
总之,同源策略就是当页面向接口发请求的时候,页面的URL和接口的URL是同源的。
二、跨域的策略
1.JSONP(JSON and padding)
JSONP是通过 script 标签加载数据的方式去获取数据当做 JS 代码来执行 提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。换句话说,JSONP 需要对应接口的后端的配合才能实现。
举例:server.js
var http = require('http') var fs = require('fs') var path = require('path') var url = require('url') http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case '/getNews': var news = [ "第11日前瞻:中国冲击4金 博尔特再战200米羽球", "正直播柴飚/洪炜出战 男双力争会师决赛", "女排将死磕巴西!郎平安排男陪练模仿对方核心" ] /*防止中文乱码*/ res.setHeader('Content-Type','text/json; charset=utf-8') /*下面是后端为jsonp实现要做的事情*/ if(pathObj.query.callback){ res.end(pathObj.query.callback + '(' + JSON.stringify(news) + ')') }else{ res.end(JSON.stringify(news)) } break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, 'not found') res.end('<h1>404 Not Found</h1>') }else{ res.end(data) } }) } }).listen(8080)
index.js:
<!DOCTYPE html> <html lang="en"> <body> <div class="container"> <ul class="news"> </ul> <button class="show">show news</button> </div> <script> $('.show').addEventListener('click', function(){ var script = document.createElement('script'); script.src = 'http://127.0.0.1:8080/getNews?callback=appendHtml'; document.head.appendChild(script); document.head.removeChild(script); }) function appendHtml(news){ var html = ''; for( var i=0; i<news.length; i++){ html += '<li>' + news[i] + '</li>'; } console.log(html); $('.news').innerHTML = html; } function $(id){ return document.querySelector(id); } </script> </body> </html>
如图,我页面地址是localhoust,但却可以访问地址为127.0.0.1的getWeather。实现了跨域访问。
2、CORS(Cross-Origin Resource Sharing)
var http = require('http') var fs = require('fs') var path = require('path') var url = require('url') http.createServer(function(req, res){ var pathObj = url.parse(req.url, true) switch (pathObj.pathname) { case '/getNews': var news = [ "第11日前瞻:中国冲击4金 博尔特再战200米羽球", "正直播柴飚/洪炜出战 男双力争会师决赛", "女排将死磕巴西!郎平安排男陪练模仿对方核心" ] res.setHeader('Access-Control-Allow-Origin','http://localhost:8081') //res.setHeader('Access-Control-Allow-Origin','*') res.end(JSON.stringify(news)) break; default: fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){ if(e){ res.writeHead(404, 'not found') res.end('<h1>404 Not Found</h1>') }else{ res.end(data) } }) } }).listen(8081)
index.html
<!DOCTYPE html> <html> <body> <div class="container"> <ul class="news"> </ul> <button class="show">show news</button> </div> <script> $('.show').addEventListener('click', function(){ var xhr = new XMLHttpRequest() xhr.open('GET', 'http://127.0.0.1:8081/getNews', true) xhr.send() xhr.onload = function(){ appendHtml(JSON.parse(xhr.responseText)) } }) function appendHtml(news){ var html = '' for( var i=0; i<news.length; i++){ html += '<li>' + news[i] + '</li>' } $('.news').innerHTML = html } function $(selector){ return document.querySelector(selector) } </script> </html>
如果在127.0.0.1下去访问这个index,则不能收到对应的数据,如图:
但如果在localhost中去打开,因为对localhost设置了特权,因此可以访问到对应的数据。
3、降域
<html> <head> <meta charset="utf-8"> <style> .ct{ width: 910px; margin: auto; } .main{ float: left; width: 450px; height: 300px; border: 1px solid #ccc; } .main input{ margin: 20px; width: 200px; } .iframe{ float: right; } iframe{ width: 450px; height: 300px; border: 1px dashed #ccc; } </style> </head> <div class="ct"> <h1>使用降域实现跨域</h1> <div class="main"> <input type="text" placeholder="http://localhost:8080/a.html"> </div> <iframe src="http://127.0.0.1:8080/b.html" frameborder="0" ></iframe> </div> <script> //URL:http://localhost:8080/a.html document.querySelector('.main input').addEventListener('input', function(){ console.log(this.value); window.frames[0].document.querySelector('input').value = this.value; }) document.domain = "jrg.com" </script> </html>
b.html
<html> <head> <meta charset="utf-8"> <style> html,body{ margin: 0; } input{ margin: 20px; width: 200px; } </style> </head> <body> <input id="input" type="text" placeholder="http://127.0.0.1:8080/b.html"> <script> // URL: http://127.0.0.1:8080/b.html document.querySelector('#input').addEventListener('input', function(){ window.parent.document.querySelector('input').value = this.value; }) document.domain = 'jrg.com'; </script> </body> </html>
在a.html中埋下一个iframe可以调用b.html中的内容,而iframe的src对应的是在127.0.0.1下。若在localhost下打开a.html,虽然可以访问b.html中的内容,但并不能操作。
但若在127.0.0.1下打开a.html则可以进行对应操作。
假使当前页面a.jrg.com ,而iframe为b.jrg.com ,这时我们使用document.domain='jrg.com' 这样就可以操作iframe了,这就是通过降域实现操作iframe
4、postMessage