网络&安全
❓输入URL地址后发生了什么事情?
- DNS域名解析,从URL地址中获取域名地址,通过DNS服务器解析为IP地址。先本地缓存(浏览器、操作系统)》ISP网络服务商》根服务器(根域、一级域、二级域、三级域)
- 建立TCP连接,HTTP协议是基于TCP协议的,浏览器与服务端通过三次握手建立TCP连接(如果是HTTPS则是四次握手,多了因此SSL握手)。
- 下载数据,向服务端发送请求报文(header+body),服务端监听80、443端口,响应HTTP请求,返回页面数据。
- 页面解析渲染,解析HTML为DOM树,CSS为规则树,构成渲染树进行布局和渲染。这个过程会重复多次下载、解析渲染,如有其他域名的资源,则会重复前面的步骤。
- 断开连接,TCP四次挥手告别!
❓说说HTTP和HTTPS
- TCP:HTTP是建立在TCP协议之上的,TCP协议属于OSI网络模型的传输层协议。建立TCP协议需要经过三次握手:请求》确认》建立连接。
- HTTP:全称是超文本传输协议,图片、网页、视频、音频、文件都是HTTP的超文本,由浏览器“渲染”出来。优点是简单、灵活、快平台,缺点是无状态、明文传输。
- HTTP请求响应的结构:首行(请求行、响应状态行)、header、body。
- 状态码,200正常,3是重定向,4客户端错误,404资源不存在,5**服务端错误。
- HTTPS:是在HTTP的基础上添加了SSL/TLS安全层,解决数据明文传输的问题。
- 默认端口443。
- 4次握手建立链接,在HTTP的基础上,多了一次SSL链接握手。
- 采用混合加密(公私钥加密秘钥,秘钥加密数据)保障数据安全传输。
- 采用数据摘要,保障数据不被篡改。
- 采用CA数字证书防止假冒网站、中间人攻击。CA证书中包含了公钥、网站身份信息等。
- TLS是SSL的升级版,由国际化IOS组织发布。
- HTTP1.1与HTTP2.0,HTTP1.1是目前广泛支持和使用的协议版本,HTTP2.0在2015年发布,提升了传输的性能,Header支持压缩和优化,可以多路复用。
❓HTTP协议有哪些版本,什么区别?
- HTTP1.1,比较普及的协议,特点是支持了长链接,可以并行传输。缺点是服务端要排队,存在队头阻塞的现象。
- HTTP2,基于HTTPS,支持了Header的压缩和优化,在安全性、效率上提升了。服务端也支持了多了复用,并行处理请求。
- HTTP3,还比较新,基于UDP协议,同时参考了TCP,兼顾效率和可靠。
❓POST和GET有什么区别?
- 数据位置:GET在URL上,问号后面的参数;POST在body中。
- 书签/缓存/刷新:GET可书签、缓存,POST的数据不可记录书签、缓存。
- 数据长度:GET有长度限制,URL长度2048,不同浏览器不同;POST没有限制。
- 使用场景:GET多用于获取数据,POST多用于新增、删除、修改。
❓什么是跨域?如何实现跨域?
- 首先起因是由于浏览器的一个安全机制——同源,AJAX只能访问同源的服务端,即协议+域名+端口相同。
- 但有时候需要跨域访问服务,就有了相应的办法:
- JSONP利用
<script>
标签访问,服务端返回一个动态脚本,数据就在脚本里面。 - CORS(cross origin resource sharing)是为满足跨域资源访问而新增的特性,在Header上带上源地址“origin”字段,由服务端来判断是否同意访问。
- 其他还有如websocket、iframe、服务端代理等方式。
- JSONP利用
❓TCP的三次握手和四次挥手
✏️主要是在建立HTTP连接、和断开链接的时候,HTTP协议属于应用层协议,建立在TCP协议基础上。
- 建立连接时,TCP三次握手:1、客户端发生连接请求,2、服务端响应应答,3、客户端收到并发送确认报文。
- 断开连接时,TCP四次挥手:1、客户端发送断开请求,2、服务端回复收到,3、服务端验证没有问题发送可以关闭报文,4、客户端发送最后的确认关闭连接报文。客户端等待2MSL(两个最大报文生存周期)后,正式关闭TCP。
❓关于WebSocket
✏️和HTTP一样都属于应用层协议,目的是提供全双工的网络通信,没有跨域的限制。复用HTTP连接建立通道,缺点是需要用心跳机制来确保连接状态。
❓TCP与UDP
✏️都是传输层的协议,TCP需要先建立连接通道,数据传输安全、可靠,当然效率也更低。UDP不用建立连接,直接发送数据,不保证可靠到达,效率高。
❓请求头的keep-alive是什么东西?
✏️keep-alive是HTTP1.1协议中默认开启的长链接,一次建立连接,保持TCP的长链接,后续HTTP请求可以复用,提升了响应效率。
缺点是服务端有队头阻塞的现象,就是服务端必须排队处理每一个请求。可以升级到HTTP2,采用多路复用并行处理的方式,不用依次排队了。
❓什么是中间人攻击?- 欺上瞒下(CA)
✏️就是在服务端、客户端中间截获数据,伪造公私钥,欺上瞒下,从而窃取数据。防范办法就是采用CA证书,客户端会验证CA证书的合法性。
CA证书中包含了公钥、网站身份信息等。
❓跨站脚本攻击XSS(Cross site scripting)
✏️主要是在表单输入的地方注入JS脚本内容(如<script>alert('XSS')</script>
),从而攻击当前网站,和SQL注入攻击的路径类似,都是非法输入恶意代码。
- 对前端输入的内容做验证,如电话号码、邮箱、特殊字符等。
- 对内容转义,vue中用
v-text
、v-bind
、文本插值{{}}
绑定都是自动做了转义的,因此谨慎使用v-html
。
Cross site scripting 的简称为XSS,是因为CSS就重名了。
❓跨站请求伪造CSRF(Cross site request forgery)
✏️钓鱼网站利用已登录的cookie凭证发起非法请求,从而完成攻击。
- 通常需要用到跨域请求,服务端应该对跨域请求进行白名单验证(referer、origin)。
- 设置客户端cookie的权限,
SameSite
:跨站不传输cookie。HTTPOnly
,客户端不可访问cookie。 - 服务端添加token验证,而不仅仅靠cookie
- 在产品设计上,对一些危险操作,如支付转账,应该加上客户验证步骤。
❓JSONP的安全问题
- 对于服务端,防止非法访问,验证请求的referer、origin是否在白名单。
- 对于客户端,防止返回的内容存在跨站脚本,对callback返回的内容进行转义。
❓CSP安全策略配置
✏️CSP(Content Security Policy)网页内容安全策略,相当于配置了一个白名单,告诉浏览器那些外部资源可以加载、执行,具体实现是由浏览器完成的。
- 通过Header配置:
Content-Security-Policy: script-src 'self';
- 通过HTML的的meta标签:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'>
前端工程化
❓模块化
module模块是前端工程化的基础,模块让JS可以拆分封装,实现了代码的隔离和依赖。一个JS文件就是一个模块,是一个独立的作用域,模块之间通过export、import来实现导出、导入。
❓包管理
✏️
❓打包优化
一个JS文件就是一个模块,
性能优化
❓页面性能优化的基本策略
✏️就是从页面的整个生命周期上全面分析,找出瓶颈点进行优化,这里只针对前端部分的优化,后端还会涉及数据库、服务的优化。
1、网络连接:尽快的连接到服务器
- DNS域名解析,避免太多第三方域名、
dns-prefetch
域名预解析等。 - HTTP连接,TCP握手建立连接,使用长链接、升级HTTP2(压缩、并行)。
2、资源加载:尽快的完成资源的加载
- 减少资源大小:JS、CSS、图片等文件的压缩,启用gzip,按需加载。
- 减少资源请求次数,文件合并。
- 针对图片:
- 选择合适的文件格式:jpg/png/svg/webp/gif。
- 使用响应式图片(img srcset / picture),小尺寸设备使用小图片。
- 小图使用雪碧图合并,或者base64编码嵌入文档。
- 图片懒加载,使用
IntersectionObserver
交叉观察器。
- 合理使用缓存,设置静态资源的HTTP缓存(强缓存、协商缓存)。
- 增加服务端网络带宽,使用CDN,提升下载速度。
3、浏览器解析渲染:尽快的完成页面渲染
- 根据情况合理使用async、defer,避免阻塞Dom解析。
- CSS少使用通配符,减少层数。支持GPU加速的CSS:transform、opacity、filter、will-change。
- 避免频繁的DOM操作引发的页面回流、重绘,图片规定高度、脱离文档流、使用transform等。
- 事件的防抖和节流,避免无效的操作。
❓Vue的优化策略?
Object.freeze()
冻结不会变的数据。v-once
申明不会更新的数据绑定。v-if/v-show
,频繁切换的场景用v-show
。v-for
设置唯一key,避免和v-if
同时用,此时可用computed
计算属性先过来集合。- 合理使用
<keep-alive>
组件缓存。 - 路由懒加载:
component: () => import('@/views/Home.vue')
。 - 尽量避免大量数据的的加载渲染:
- 拆分数据,避免一次性加载太多数据,如分页、滚动加载、树的懒加载等。
- 采用虚拟化技术,如vue-virtual-scroller,只渲染可见部分的数据。
❓
✏️
设计模式
设计模式是编程中的最佳实践,用于解决一些复杂的代码问题,可以让你的代码更简洁、更高效,高内聚、低耦合。在JS中结合TS实现会更优优雅,需要用到接口、类、泛型。
- 单一职责模式:一段代码(类、函数)只有一个职责,高内聚、低耦合,避免各种功能堆积在一起。
- 开闭原则:对扩展开发,对修改关闭,就封装不变的,开放可扩展的接口。策略模式、
- 里氏替换原则:子类可以替换父类,继承的关系。
- 依赖倒转原则:依赖于抽象接口,而不是具体的实现,具体实现可以。策略模式、抽象工厂。
- 接口隔离原则:采用最小接口原则,不同功能用不同接口定义。
❓单例模式:全局唯一实例
✏️用类的静态方法实现,获取的时候判断是否已存在,不存在就new一个实例。用TS的话还可以用泛型,实现一个通用的单例工厂。
class MySingle {
constructor() {
//创建实例
}
static getInstance() {
//静态方法属于类本身,这里的this也就指向类本身
if (!this.instance)
this.instance = new MySingle()
return this.instance;
}
}
//使用
MySingle.getInstance()
❓策略模式:将策略算法和策略的执行器分开,可灵活扩展策略。
✏️封装一个策略的执行器,然后策略算法可以灵活的扩展添加。
//计算薪资,根据员工绩效等级(A、B、C)计算薪资
const salaryCenter = {
//计算薪资
getSalary(value, mode) {
return this[mode](value);
},
//添加绩效等级及其策略
addStrategy(mode, strategyFunc) {
this[mode] = strategyFunc;
}
}
//添加不同绩效等级的策略,这就是对扩展开放
salaryCenter.addStrategy('A', function (value) {
return value * 1.2;
});
salaryCenter.addStrategy('B', function (value) {
return value * 1;
});
salaryCenter.addStrategy('C', function (value) {
return value - 200;
});
//使用
salaryCenter.getSalary(100,'A')
❓工厂模式:把new()封装起来,面向抽象编程。
✏️根据一个标识来创建实例,TS中可以用接口来约束创建的实例。
//工厂模式
class AnimateFactory {
static Create(type) {
switch (type) {
case 'bird':
return new Bird();
case 'duck':
return new Duck();
default:
console.log('type not exist:' + type);
}
}
}
❓发布订阅模式:发布消息-订阅消息事件
✏️由一个消息中心来管理订阅的消息事件,通过发送消息来触发事件。用于不同组件之间的通信。
//消息中心
class EventCenter {
constructor() {
this.task = {};
}
//订阅消息,注册消息处理回调
registry(type, func) {
this.task[type] ??= [];
//支持重复注册
this.task[type].push(func);
}
// 发送消息,触发消息回调的执行
emit(type, ...args) {
if (!this.task[type]) return;
this.task[type].forEach(func => {
func.apply(this, args);
})
}
//用单例返回消息中心实例
static getInstance() {
this.instance ??= new EventCenter();
return this.instance;
}
}
//使用,注册、发布
EventCenter.getInstance().registry('ele', (food) => {
console.log('饿了,开始做' + food);
})
EventCenter.getInstance().emit('ele', '面条')
❓观察者模式:对一个目标对象进行观察(监测),当目标变化时触发响应回调。
✏️Vue2的双向绑定,监听数据变化就是拦截属性的get、set,观察数据的变更。