跨域
在node.js服务中,向其他服务器发送http/https请求数据,是否会发生跨域呢?
举个例子
// 在https://www.google.com所在的node服务程序中
async function get(){
const rsp = await fetch('https://www.baidu.com')
}
// 这个fetch请求是否涉及跨域呢?
当然是不会了,跨域一般是发生在浏览器,是浏览器自己的安全策略。
node服务不是运行在浏览器中,所以不涉及跨域
即使是有同源策略,但是不影响客户端发送请求给服务器,服务器还是会返回数据,只是被浏览器拦截了
- 同源策略
浏览器故意设置的一个功能限制 - CORS
突破浏览器设置的一个方法 - JSONP
IE时代的一个妥协
什么叫同源?
源
window.origin 或 location.origin可以得到当前源
源 = 协议 + 域名 + 端口号
如果两个URL的协议域名端口号完全一致,那么这两个URL就是同源的。
同源策略
不同源的页面之间不准相互访问数据。
如果JS运行在源A中,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨域。
浏览器设置同源策略的目的是为了保护用户隐私。
修改host
右键打开记事本以管理员身份运行=》文件=》打开C:\Windows\System32\drivers\etc
当我们用黑客网站跨域取qq空间的friends.json数据时,虽然请求成功,但是无法下载数据
注意:同源策略限制的是数据访问,我们引用CSS、JS和图片的时候并不算数据访问,其实并不知道其内容(就像我们不知道CSS的第一个字符),我们只是在引用。
如何解决这个问题呢?
如何跨域?
解法一:CORS(推荐)
添加允许访问的网站到白名单
当使用XMLHttpRequest发送请求时,如果浏览器发现违反了同源策略就会自动加上一个请求头 origin;
后端在接受到请求后确定响应后会在 Response Headers 中加入一个属性 Access-Control-Allow-Origin;
浏览器判断响应中的 Access-Control-Allow-Origin 值是否和当前的地址相同,匹配成功后才继续响应处理,否则报错
缺点:忽略 cookie,浏览器版本有一定要求
这种方式分为两种请求:
一种是简单请求,另一种是非简单请求
简单请求跨域:
请求方式为HEAD、POST 或者 GET
非简单请求跨域:
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json
解法二:JSONP
(JSONP和JSON没有半毛钱关系)
IE不支持CORS的场景。
没有CORS我们怎么跨域呢?
虽然我们不能访问json,但是我们可以引用js啊,虽然js不是数据,但是我们可以让JS包含数据。
- 在qq.com下创建一个friends.js 。
- marshall.js 事先定义好window.xxx函数,然后用script标签引用/friends.js,/friends.js执行window.xxx({friends:[...]})
- 然后marshall.com就通过window.xxx获取到数据了
- window.xxx就是一个回调
解法三:服务器中转
浏览器对跨域有限制,但是服务器没有。如果某服务器没有跨域方法,我们就不找他要数据,而是找一个中转服务器,用中转服务器去找目标服务器要数据,服务器和服务器之间是没有限制的。
例子:本地开发使用框架,在开发阶段,webpack里可能会使用代理服务器,代理服务器的一部分作用就是作为中转服务区,实现跨域请求。
面试题:JSONP是什么?
创建一个script去请求另一个网站的JS,然后JS里边会夹带一些数据,这些数据会在我的网站上调用一个全局函数运行,这就是JSONP。
{由于跨域的时候,如果当前浏览器不支持CORS,我们就必须用另一种方式来实现跨域,于是我们就请求一个JS文件,这个JS文件会执行一个回调,这个回调里边就有我们的数据。(补充:这个回调的名字是可以用随机数随机生成的,把这个名字以callback的方式传给后台,回台会再次把这个函数返回给我们并执行。)}
优点:
- 兼容IE
- 可以跨域
缺点:
由于他是script标签,
- 它只能发get请求。(不支持post)
- 拿不到状态码,拿不到header
(他读不到AJAX那么精确的状态,他不知道状态码是什么,也不知道响应头是什么,只知道成功或失败)
网友评论