概念
当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求。例如,XMLHttpRequest
和 Fetch遵循同源策略。因此,使用 XMLHttpRequest或 Fetch 的Web应用程序只能将HTTP请求发送到其自己的域。为了改进Web应用程序,开发人员要求浏览器厂商允许跨域请求。
解决方案
1. 如何使用CORS策略来进行跨域操作
跨域资源共享(CORS)机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在发送AJAX请求中使用CORS来降低HTTP请求所带来的风险。
1.1 简单模式
- 在服务器后端方设置响应头response.setHeader ('Access-Control-Allow-Origin','http://xxxxx.com') 使用node.js监听端口;('http://xxxxx.com' 为你要跨域的域名和端口)
response.setHeader('Access-Control-Allow-Origin','http://xxxxx.com:80')
- 或在使用http-server模拟时,加上以下命令
http-server -c-1 -p --cors="Access-Control-Allow-Origin: * "
即可使AJAX在请求时,在响应头responseHeader里加入" Access-Control-Allow-Origin:* "字串,重新请求就可以得到Access-Control-Allow-Origin权限,得到数据。
1.2 复杂模式
在AJAX请求中,如果需要使用PUT/DELETE等高级方法时,会返回报错字符串'Access-Control-Allow-Method',也需要在后端服务器中设置来开放权限,加入以下语句:
response.setHeader('Access-Control-Allow-Method','GET,POST,OPTIONS')
即可得到'Access-Control-Allow-Method'内由后端指定开放的'GET,POST,OPTIONS'等权限。
2. 如何使用JSONP策略来进行跨域操作
2.1 核心逻辑
在浏览器中,只有XMLHttpRequest和Fetch会被同源原则限制,而script、css等直接请求的source和link并不会。利用这个特点,我们如果仅需要跨域来GET一个资源的话,可以直接使用<script>脚本来获得数据。
2.2 JSONP是什么
JSONP = JSON + Padding 是跨域获得的数据文件内容的一种简写方式。一般以JSONP为传输形式的返回文件格式写法如下,中间为JSON数据格式,前后有函数的包裹:
{{callback}}(
{"name":"hikari",
"age":18
});
2.3 实现方式
- 声明一个封装函数jsonp,使传入的url可以自动生成一个随机请求名称的查询字符串地址;
function jsonp(url, fn) {
var functionName = 'randomName' + parseInt(Math.random()*100000);
window[functionName] = fn;
var script = document.createElement('script');
script.src = url + '?callback=' + functionName;
document.head.appendChild(script)
}
- 跨域端的数据文件xxx.js的内容写为JSONP标准格式:
{{callback}}({"name":"hikari", "qb":500});
- 跨域端的服务器后台文件内加入获取查询字符串的语句,并将发送来的查询字符串名声明为callback,在响应时,将callback替换入xxx.js的函数名。
if(path === '/xxx.js'){
var string = fs.readFileSync('./xxx.js','utf8')
var callback = query.callback;
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.end(string.replace('{{callback}}',callback))
}
- 执行jsonp,传入url和一个回调函数打印出结果;
jsonp('http://qq.com:81/xxx.js', function (data) {
console.log('第一次的数据');
console.log(data)
});
jsonp('http://qq.com:81/xxx.js', function (data) {
console.log('第二次的数据');
console.log(data)
});
- 得到响应的数据为randomName+一个5位随机数的执行函数;
randomName91058({"name":"hikari", "qb":500});
得到的控制台信息为
第一次的数据
{name: "hikari", qb: 500}
第二次的数据
{name: "hikari", qb: 500}
2.4 其他方法
jQuery也为JSONP设置了对应方法,可以直接调用。
$.ajax({
url: 'http://qq.com:81/xxx.js',
type: 'GET',
dataType: 'jsonp',
success: function(data){
console.log('jquery得到的数据');
console.log(data)
}
});
得到的响应数据为:
jQuery21402045766844241943_1502793793916({"name":"hikari", "qb":500});
控制台结果为
jquery得到的数据
{name: "hikari", qb: 500}
总结
CORS策略 和 JSONP策略有何异同?
- JSONP是Script脚本,而CORS策略是由JS发起的AJAX请求;
- JSONP只能GET数据,AJAX可以请求GET、POST以及各种Methods;
- JSONP安全性有限,可以任意访问,并没有同源策略的限制,而CORS可以由后端指定域名访问,适合更高级的管理需求;
网友评论