前端面经整理
Posted 365/24/60
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端面经整理相关的知识,希望对你有一定的参考价值。
节流、防抖
防抖
<div>
<input type="text" id="input">
</div>
<script>
listenInput = ()=>{
console.log(\'输入结束,调用接口\');
}
function debounce(fn , wait){
let start = Date.now() , end , st
return ()=>{
end = Date.now()
if(end - start < wait){
clearTimeout(st)
st = setTimeout(() => {
fn()
}, wait);
}else{
st = setTimeout(() => {
fn()
}, wait);
}
start = Date.now()
}
}
let input = document.querySelector(\'#input\')
input.oninput = debounce(listenInput , 1000)
</script>
节流
<div>
<input type="text" id="input">
</div>
<script>
listenClick = ()=>{
console.log(\'移动\');
}
function throttling(fn , wait){
// 节流
let start = Date.now() , end
return ()=>{
end = Date.now()
if(end-start>=wait){
fn()
start = Date.now()
}
}
}
document.onmousemove = throttling(listenClick ,1000)
</script>
排序算法
快速排序
let quickSort = function(arr){
let low = 1 , high = arr.length-1 , key = arr[0]
while(high > low){
if( arr[low] > key ){
let temp = arr[high]
arr[high--] = arr[low]
arr[low] = temp
}else{
arr[low-1] = arr[low++]
}
}
arr[low] = key
low > 0 && quickSort(arr.slice(0 , low))
low < arr.length-1 && quickSort(arr.slice(low+1))
}
二分查找
let binarySearch = function(arr, num){
let low = 0 , high = arr.length , mid
while(high > low){
mid = Math.floor((low+ high)/2)
if(arr[mid] === num ){
return mid
}else if(arr[mid] > num){
high = mid-1
}else{
low = mid +1
}
}
return -1
}
归并排序
let mergeSort = function(arr){
if(arr.length === 1){
return arr
}else if(arr.length > 1){
let mid = Math.floor(arr.length / 2)
let arrL = mergeSort(arr.slice(0 , mid))
let arrR = mergeSort(arr.slice(mid))
let llen = arrL.length , rlen = arrR.length , ret = [] , l = 0 , r = 0
while(llen > l && rlen > r ){
if(arrL[l] > arrR[r]){
ret.push(arrR[r++])
}else{
ret.push(arrL[l++])
}
}
if(l < llen || r < rlen){
ret = ret.concat(l < llen ? arrL.slice(l) : arrR.slice(r))
}
return ret
}
}
https实现原理
http存在的问题:
- 通信使用明文
- 无法证明报文的完整性,可能被篡改信息
- 不验证对方的身份,可能伪装
对称/非对称加密的特点
对称/非对称加密的特点:
- 对称加密:加密和解密使用同一个密钥
- 密钥可能落入他人之手,失去加密的意义
- 非对称加密:私有密钥、公开密钥(任何人获得)
- 黑客窃取到公开密钥,解密交流信息
- 公钥不包含身份信息,存在中间人攻击
- 加密、解密过程消耗时间大,效率低
解决内容可能被窃听:
交换密钥(后续会话)使用非对称加密,客户端使用服务器的公开密钥 加密 会话密钥 发送给 服务器
- 后续会话使用 会话密钥 加密通话
数字签名特点:
- 能确定发送方的身份
- 确定信息的完整性,确认未被篡改
生成数字签名:
如何证明公钥是服务器的 => 证书颁发机构(Certificate Authority,CA),CA 生成服务器的公钥的数字签名(证书),而客户端内置受信任的CA的证书(CA的公钥)
数字证书:确定发送方只会是真正的发送方发送过(即公钥未被截取),服务器公钥是该服务器的
- 服务器的运营人员向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证
- CA通过线上、线下等多种手段验证申请者提供信息的真实性
- 如信息审核通过,CA会向申请者签发认证文件-证书,包含:
- 明文部分:申请者(服务器)公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文
- 签名部分:明文=散列函数=>CA私钥加密=>签名
- 客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件
- 客户端使用对应的 CA 公钥解密签名数据,确定是否合法,合法则该服务器的公钥是值得信赖的
HTTPS工作流程:
前端攻击有哪些? 如何防范
XSS攻击本质:恶意代码未经过滤,与网站正常的代码混在一起,而浏览器是无法辨认哪些脚本是恶意的导致恶意脚本被执行
XSS:其实我简称CSS,Cross-Site Scripting,跨站脚本攻击
根据攻击来源分类:- 反射型XSS:
- 攻击者构造出特殊的url,其中包含恶意代码(需要用户主动点击,往往装扮的很诱人)
- 用户打开带有恶意代码的url时,网站服务端将恶意代码从url取出,拼接在html中返回给用户
- 浏览器接受到之后立即执行,可以窃取用户数据
- DOM型XSS:
- 前端不严谨,使用 .innerHTML、.outerHTML、.appendChild、document.write() 等API
- 同上,构造除了恶意的DOM片段,被插入了
恶意DOM片段:
<a href="#" onclick="doAttack()">
click me
<script type="text/javascript">
function doAttack() {
while (true) {
alert(\'u are under attack\');
}
}
</script>
</a>
XSS攻击防范
冷兵器时代:(无间道之处处防范)
- 反射型XSS:
app.get(\'/welcome\', function(req, res) {
//对查询参数进行编码,避免反射型 XSS攻击
res.send(`${encodeURIComponent(req.query.type)}`);
});
- DOM型XSS:
- 对于url链接(例如图片的src属性),那么直接使用 encodeURIComponent 来转义
- 非url,我们可以这样进行编码:
function encodeHtml(str) {
if(!str) return \'\';
return str.replace(/"/g, \'"\')
.replace(/\'/g, \''\')
.replace(/</g, \'<\')
.replace(/>/g, \'>\')
.replace(/&/g, \'&\');
}
- 存储型XSS:
- 前端数据传递给服务器之前,先转义/过滤
- 服务器接收到数据,在存储到数据库之前,进行转义/过滤
- 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义/过滤
CSP:Content-Security-Policy(二向箔划痕打击)
- 如何使用:
Content-Security-Policy: default-src \'self\'
//想要所有内容均来自站点的同一个源 (不包括其子域名):
CSRF攻击:跨站请求伪造,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
CSRF:Cross-Site Request Forgery,(伪装者之披着羊皮的狼)
- 受害者登录A站点,并保留了登录凭证(Cookie
- 攻击者诱导受害者访问了站点B
- 站点B向站点A发送了一个请求,浏览器会默认携带站点A的Cookie信息
- 站点A接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求
- 站点A以受害者的名义执行了站点B的请求
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击
CSRF攻击防范
- 添加验证码(体验不好,繁琐)
- 可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开
- 服务端给用户生成一个token,加密后传递给用户
- 用户在提交请求时,需要携带这个token
- 服务端验证token是否正确
点击劫持攻击:在一个Web页面中隐藏了一个透明的iframe,用外层假页面诱导用户点击,实际上是在隐藏的frame上触发了点击事件进行一些用户不知情的操作
性感荷官在线发牌...(好胆你就点)
攻击过程:- 攻击者构建了一个非常有吸引力的网页(跟前面有区别:攻击者构造的网页)
- 将被攻击的页面放置在当前页面的 iframe 中
- 使用样式将 iframe 叠加到非常有吸引力内容的上方
- 将iframe设置为100%透明
- 你被诱导点击了网页内容,你以为你点击的是***,而实际上,你成功被攻击了
攻击防范:
if (top.location !== window.location) {
top.location = window.location; }
- 另外HTML5中 iframe的 sandbox 、IE中iframe的security 都可以限制iframe中的脚本执行
Web前端性能优化
网页内容
减少http请求:
- CSS Sprites:雪碧图
- 字体图标:
- 需要请求的脚本和样式表合并起来,较少请求次数
减少 DNS 查询次数:
DNS 查询:浏览器缓存 => 操作系统缓存 => DNS查找
- 使用 DNS 缓存
- 缓存时间长,有利于重复利用
- 缓存时间短:有利于及时检测目标站点 IP 更新
- 将需要请求的内容放在同一个域名
- 但会出现下载资源排队现象,一个网站使用 2~4个 域
避免页面跳转
缓存AJAX(Asynchronrous Javascript and XML)
--------------------------------------------------------
添加Expires头:提醒客户端可以缓存数据到一定时间
- 初始形态:
Expires: Fri, 18 Mar 2016 07:41:53 GMT
- 要求服务求与客户端时钟严格同步:过期日期需要经常检查
- HTTP1.1来临:
Cache-Control: max-age=12345600
- max-age、Expires同时存在,max-age 更顶,指定失效时间
- ETags:Entity Tag,实体标签:一个特殊字符串来标识某个资源的“版本”。工作原理:
- 客户端第一次请求资源:服务端响应:200,响应头部包含ETag的信息(ETag "
6ab823201a4ece1:0
") - 客户端再次请求该资源:请求头添加一行:
If-None-Match "6ab823201a4ece1:0"
- 此次,服务器会比对 ETag的值,如果没有变化,会返回
304
状态码,响应体不需要包含任何实际内容- 浏览器得到304之后,直接使用本地缓存的版本
- 客户端第一次请求资源:服务端响应:200,响应头部包含ETag的信息(ETag "
压缩组件:HTTP1.1之后
- 客户端:表达自己接受的类型,
Accept-Encoding: gzip,deflate
- 服务器端:
Content-Encoding: gzip
--------------------------------------------------------
延迟加载
- 网页最初加载需要的最小内容集
- 比较激进的做法是开发网页时确保没有JavaScript也能完成基本工作
- 然后通过延迟加载完成一些高级的功能
提前加载
CDN:(Content Delivery Network)那日容分发网络,就近获取目标服务器的数据
https://juejin.cn/post/684490373633933
https://juejin.cn/post/6844904155077672968
以上是关于前端面经整理的主要内容,如果未能解决你的问题,请参考以下文章