跨领域,不可知的基本概念
跨域这两个字在前端开发者身上都会碰到的,无论你在工作上或者面试中无可避免会遇到这个问题。尤其是最初搭建项目的时候。但单纯只是为了面试背几个方案,也无足轻重,重要是理解透彻,懂得跨域的前因后果,以及当下最为方便快捷的解决方案,才是上上策。而不是当时网上搜几篇文章看着将项目配置一下问题解决了,然后就将它抛之脑后了。日子虽然可以照常混,但是下次再遇到这个问题的时候又是一顿乱搜,效率实属不高,面试的时候也是要再次查找各种资料去了解。
为了全面的了解跨域的前世今生,彻底搞懂这个东西!于是就有了这篇文章。
为什么会存在跨域这个问题
因为存在浏览器同源策略,所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到,跨域限制主要的目的就是为了用户的上网安全。
没有同源策略限制的两大危险场景
如果浏览器没有同源策略,会存在什么样的安全问题呢。下面从 DOM 同源策略和 XMLHttpRequest 同源策略来举例说明:
如果没有 DOM 同源策略,也就是说不同域的 iframe 之间可以相互访问,那么黑客可以这样进行攻击:
- 做一个假网站,里面用 iframe 嵌套一个银行网站
http://mybank.com
。 - 把 iframe 宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。
- 这时如果用户输入账号密码,我们的主网站可以跨域访问到
http://mybank.com
的 dom 节点,就可以拿到用户的账户密码了。
如果 XMLHttpRequest 同源策略,那么黑客可以进行 CSRF(跨站请求伪造) 攻击:
- 用户登录了自己的银行页面
http://mybank.com
,http://mybank.com
向用户的 cookie 中添加用户标识。 - 用户浏览了恶意页面
http://evil.com
,执行了页面中的恶意 AJAX 请求代码。 -
http://evil.com
向http://mybank.com
发起 AJAX HTTP 请求,请求会默认把http://mybank.com
对应 cookie 也同时发送过去。 - 银行页面从发送的 cookie 中提取用户标识,验证用户无误,response 中返回请求数据。此时数据就泄露了。
- 而且由于 Ajax 在后台执行,用户无法感知这一过程。
因此,有了浏览器同源策略,我们才能更安全的上网。
浏览器的同源策略
同源策略(Same Origin Policy,SOP)是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本(如 Java)对不同域的服务进行跨站调用(通常指使用请求)。它能帮助阻隔恶意文档,减少可能被攻击的媒介。这是一个用于隔离潜在恶意文件的关键的安全机制。同源策略机制是一种约定,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略。则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础上的,浏览器只是针对同源策略的一种实现。
同源策略是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响,比如源a的js不能读取或设置引入的源b的元素属性。
同源的定义
所谓同源是指:两个页面具有相同的域名、协议、端口,三个要素缺一不可。
同源策略带来的问题
- 一级域名相同,只是二级域名不同的同一所有者的网页被限制(Cookie、LocalStorage、IndexDB的读取)
- 无法跨域发送 AJAX 请求
- 无法操作 DOM
- Q:为什么 Form 表单可以跨域发送请求,而 AJAX 不可以。
A:因为 Form 表单提交之后会刷新页面,所以即使跨域了也无法获取到数据,所以浏览器认为这个是安全的。而 AJAX 最大的优点就是在不重新加载整个页面的情况下,更新部分网页内容。如果让它跨域,则可以读取到目标 URL 的私密信息,这将会变得非常危险,所以浏览器是不允许 AJAX 跨域发送请求的。
跨域的原理
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略
造成的。
同源策略,是浏览器对 JavaScript 实施的安全限制,只要协议、域名、端口
有任何一个不同,都被当作是不同的域。
跨域原理,即是通过各种方式,避开浏览器的安全限制
。
跨域解决方案
最初做项目的时候,使用的是jsonp,但存在一些问题,使用get请求不安全,携带数据较小,后来也用过iframe,但只有主域相同才行,也是存在些问题,后来通过了解和学习发现使用代理和proxy代理配合起来使用比较方便,就引导后台按这种方式做下服务器配置,在开发中使用proxy,在服务器上使用nginx代理,这样开发过程中彼此都方便,效率也高;现在h5新特性还有 windows.postMessage()
-
JSONP:
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链 接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。
步骤:
1. 去创建一个script标签
2. script的src属性设置接口地址
3. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
4. 通过定义函数名去接受返回的数据
//动态创建 script
var script = document.createElement('script');
// 设置回调函数
function callbackFunction(data) {
console.log(data);
}
//设置 script 的 src 属性,并设置请求地址
script.src = 'https://api.ycsnews.com/test?callback=callbackFunction';
// 让 script 生效
document.body.appendChild(script);
laravel php 后端代码
public function test(Request $request){
//获取回调函数名
$callback= $request->callback;
//服务端返回数据
$data = [
[
'code'=>0,
'data'=>[1,2,3,4,5]]
];
//动态执行回调函数
//方法1:
return response()->jsonp($callback, $data);//接收的方法名和传输的数据
//方法2:
// return response()->json($data)->setCallback($callback);
}
JSONP 的缺点: JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。
-
document.domain 基础域名相同 子域名不同
-
window.name 利用在一个浏览器窗口内,载入所有的域名都是共享一个window.name
-
CORS CORS(Cross-origin resource sharing)跨域资源共享 服务器设置对CORS的支持原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求。实现
CORS
通信的关键是服务器。只要服务器实现了CORS
接口,就可以跨源通信。 -
proxy代理 目前常用方式。 通俗点说就是客户端浏览器发起一个请求会存在跨域问题,但是服务端向另一个服务端发起请求并无跨域,因为跨域问题归根结底源于同源策略,而同源策略只存在于浏览器
那么我们是不是可以通过
Nginx
配置一个代理服务器,反向代理访问跨域的接口,并且我们还可以修改Cookie
中domain
信息,方便当前域Cookie
写入 -
window.postMessage() 利用h5新特性window.postMessage()
-
Websocket
跨域配置
Vue-CLI中代理的多种配置
Vue-CLI 是基于 webpack
的,通过 webpack-dev-server
在本地启动脚手架,也就是在本地启动了一个 Node
服务,来实时监听和打包编译静态资源,由于都是封装好的,只需要配置即可,我们在 vue.config.js
中配置代理如下,写法很多,列几个常见的自行选择
module.exports = {
//...
devServer: {
proxy: {
'/api': 'http://www.hahaha.com'
}
}
}
复制代码
如上所示时,当你请求 /api/abc
接口时就会被代理到 http://www.hahaha.com/api/abc
上一篇: 深入了解范围和闭包
下一篇: 自然语言理解(NLU)