原文地址: https://github.com/HolyZheng/...
了解几个跨域的方案,而且经过简单实践进行体会。javascript
可是,咱们如何进行实践呢?在哪发请求?向什么服务器发请求?很简单,就在当前网页,打开控制台,输入请求的代码html
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.send();
那么咱们就能够以当前页面url做为origin,向http://127.0.0.1:8888/ ,发送请求GET请求了。
同时在本地建立一个node服务前端
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, { 'Content-Type': 'text/plain' }); response.end('request success!!!'); }).listen(8888); console.log('Server running at http://127.0.0.1:8888/');
这样咱们就有服务器了,你能够很轻松的跟着这遍文章来实践了,而后从当前网页发送get请求到本地服务,理所固然跨域了。java
ps: github网站不行(本文最初再github上编写),会引起csp错误,此错误是用于防止内容注入攻击的,不得不说,大网站安全措施作得就是好,转战segmentfault作实践。
cors(跨域资源共享 Cross-origin resource sharing),它容许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它须要浏览器和服务器的同时支持。node
cors 分为两种请求,简单请求和非简单请求,关于cors的更详细介绍,推荐阮一峰老师的 跨域资源共享 CORS 详解,本文注重实践。
正如上方的例子即是一个简单请求git
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.send();
如何解决此案例的跨域问题呢?
浏览器端,浏览器会自动在请求头中添加 origin 字段,咱们不须要操做。github
Request Headers: Origin: https://github.com
服务端,Access-Control-Allow-Origin属性,咱们须要服务端设置此属性,指定容许的请求源域名,能够经过指定为 *
来指定因此域名。后端动起来:json
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' }); response.end('request success!!!'); }).listen(8888); console.log('Server running at http://127.0.0.1:8888/');
重启服务,再尝试segmentfault
此次没有再报错了,咱们看看服务器放回了什么
nice!跨域成功!后端
一样咱们在控制台输入一下代码进行put(非简单请求)
var url = 'http://127.0.0.1:8888/'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.send();
毫无心外的报错
在进行非简单请求的时候,浏览器会先发送一次OPTION请求来“预检”(preflight)该请求是否被容许,请求头中会经过Access-Control-Request-Method
,Access-Control-Request-Headers
来告诉服务器我须要用到的方法和字段,服务器经过返回的头部信息中的Access-Control-Allow-Origin
,Access-Control-Allow-Method
来告诉浏览器该跨域请求是否被容许。修改后端代码:
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT' }); response.end('request success!!!'); }).listen(8888); console.log('Server running at http://127.0.0.1:8888/');
能够看到浏览器会先发送一个预检
当确认容许跨域以后,之后再发送该请求,就会省去预检处理,之间看成简单请求来操做。很明显,修改了后端代码后,此次的put请求时成功的。这里就不继续上图了。
cors(跨域资源共享 Cross-origin resource sharing),它容许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它须要浏览器和服务器的同时支持。
Access-Control-Allow-Methods
,Access-Control-Allow-Headers
,Access-Control-Allow-Origin
等字段,指定容许的方法,头部,源等信息。jsonp的原理就是利用就是利用script
标签没有跨域限制,能够经过script
标签的src属性发送GET
请求。咱们继续尝试,先把后端有关跨域的设置去掉,并重启服务
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, { 'Content-Type': 'text/plain' }); response.end('request success!!!'); }).listen(8888); console.log('Server running at http://127.0.0.1:8888/');
打开咱们的控制台输入一下代码,利用script标签进行jsonp请求
var script = document.createElement('script'); script.type = 'text/javascript'; script.src = `http://127.0.0.1:8888/`; document.head.appendChild(script);
能够看到,后端正常的返回了
request success !!!
并且该请求为GET
请求
Request URL: http://127.0.0.1:8888/ Request Method: GET Status Code: 200 OK Remote Address: 127.0.0.1:8888 Referrer Policy: no-referrer-when-downgrade
可是咱们如今只是成功发送了一个跨域请求,可是咱们不像XMLHttpRequest那样能够在res.responseText中拿到数据,经过jsonp咱们该怎么拿到请求的数据呢?方法就是先后端约定一个callback字段名,来传递函数名,前端经过该函数来拿到数据。前端代码修改成:
var script = document.createElement('script'); script.type = 'text/javascript'; script.src = `http://127.0.0.1:8888/?callback=onBack`; document.head.appendChild(script); function onBack (res) { console.log(JSON.stringify(res)); // 请求完后删除添加到页面上的script标签 var head = document.head head.removeChild(script) }
经过callback字段来传递函数名onBack,后端代码修改成
var http = require('http') var urlTool = require('url') // json 数据 var data = {'methods': 'jsonp', 'result': 'success'}; http.createServer(function (request, response) { var params = urlTool.parse(request.url, true) console.log(params) response.writeHead(200, { 'Content-Type': 'text/plain' }); if (params.query && params.query.callback) { // callback(data) var str = `${params.query.callback}(${JSON.stringify(data)})` } response.end(str); }).listen(8888); console.log('Server running at http://127.0.0.1:8888/');
重启后端服务,而且在控制台输入代码,能够看到结果:
咱们拿到了数据,而且经过onBack函数将他输出到了控制台上!
script
标签没有跨域限制的特色,经过script
标签的的src属性发送GET
请求。同源策略:同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式,这是一个用于隔离潜在恶意文件的重要安全机制。若是两个页面拥有 相同 的 协议(protocol),端口(若是指定),和 主机,那么这两个页面就属于同一个源(origin)。