关于【Step-By-Step】
Step-By-Step (点击进入项目) 是我于
2019-05-20
最先的一个项目,每一个工作日宣布一道面试题。每一个周末我会仔细浏览人人的答案,整顿最一份较优答案出来,因本人程度有限,有误的处所,人人实时斧正。
假如想 加群 进修,关注民众号,增添我为挚友,我拉你进群。
本周面试题一览:
- 什么是XSS进击,XSS 进击可以分为哪几类?我们怎样提防XSS进击?
- 怎样隐蔽页面中的某个元素?
- 浏览器事宜代办机制的道理是什么?
- setTimeout 倒计时为何会涌现偏差?
11. 什么是XSS进击,XSS进击可以分为哪几类?我们怎样提防XSS进击?
1. XSS进击
XSS(Cross-Site Scripting,跨站剧本进击)是一种代码注入进击。进击者在目的网站上注入歹意代码,当被进击者上岸网站时就会实行这些歹意代码,这些剧本可以读取 cookie,session tokens,或许别的敏感的网站信息,对用户举行垂纶敲诈,以至提议蠕虫进击等。
XSS 的实质是:歹意代码未经过滤,与网站一般的代码混在一同;浏览器没法区分哪些剧本是可托的,致使歹意剧本被实行。由于直接在用户的终端实行,歹意代码可以直接猎取用户的信息,应用这些信息假装用户向网站提议进击者定义的要求。
XSS分类
依据进击的泉源,XSS进击可以分为存储型(耐久性)、反射型(非耐久型)和DOM型三种。下面我们来细致相识一下这三种XSS进击:
1.1 反射型XSS
当用户点击一个歹意链接,或许提交一个表单,或许进入一个歹意网站时,注入剧本进入被进击者的网站。Web服务器将注入剧本,比方一个错误信息,搜刮结果等,未举行过滤直接返回到用户的浏览器上。
反射型 XSS 的进击步骤:
- 进击者组织出迥殊的
URL
,个中包括歹意代码。 - 用户翻开带有歹意代码的
URL
时,网站服务端将歹意代码从URL
中掏出,拼接在 HTML 中返回给浏览器。 - 用户浏览器接收到相应后剖析实行,混在个中的歹意代码也被实行。
- 歹意代码盗取用户数据并发送到进击者的网站,或许假装用户的行动,挪用目的网站接口实行进击者指定的操纵。
反射型 XSS 破绽常见于经由过程 URL
通报参数的功用,如网站搜刮、跳转等。由于须要用户主动翻开歹意的 URL
才见效,进击者往往会连系多种手腕引诱用户点击。
POST 的内容也可以触发反射型 XSS,只不过其触发前提比较刻薄(须要组织表单提交页面,并指导用户点击),所以异常少见。
假如不愿望被前端拿到cookie,后端可以设置 httpOnly
(不过这不是 XSS进击
的解决方案,只能下落受损局限)
怎样提防反射型XSS进击
对字符串举行编码。
对url的查询参数举行转义后再输出到页面。
app.get('/welcome', function(req, res) {
//对查询参数举行编码,防备反射型 XSS进击
res.send(`${encodeURIComponent(req.query.type)}`);
});
1.2 DOM 型 XSS
DOM 型 XSS 进击,实际上就是前端 JavaScript
代码不够严谨,把不可托的内容插进去到了页面。在运用 .innerHTML
、.outerHTML
、.appendChild
、document.write()
等API时要迥殊警惕,不要把不可托的数据作为 HTML 插到页面上,只管运用 .innerText
、.textContent
、.setAttribute()
等。
DOM 型 XSS 的进击步骤:
- 进击者组织出迥殊数据,个中包括歹意代码。
- 用户浏览器实行了歹意代码。
- 歹意代码盗取用户数据并发送到进击者的网站,或许假装用户的行动,挪用目的网站接口实行进击者指定的操纵。
怎样提防 DOM 型 XSS 进击
提防 DOM 型 XSS 进击的中心就是对输入内容举行转义(DOM 中的内联事宜监听器和链接跳转都能把字符串作为代码运转,须要对其内容举行检查)。
1.关于url
链接(比方图片的src
属性),那末直接运用 encodeURIComponent
来转义。
2.非url
,我们可以如许举行编码:
function encodeHtml(str) {
return str.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
DOM 型 XSS 进击中,掏出和实行歹意代码由浏览器端完成,属于前端 JavaScript 本身的安全破绽。
1.3 存储型XSS
歹意剧本永久存储在目的服务器上。当浏览器要求数据时,剧本从服务器传回并实行,影响局限比反射型和DOM型XSS更大。存储型XSS进击的缘由依然是没有做好数据过滤:前端提交数据至服务端时,没有做好过滤;服务端在接收到数据时,在存储之前,没有做过滤;前端从服务端要求到数据,没有过滤输出。
存储型 XSS 的进击步骤:
- 进击者将歹意代码提交到目的网站的数据库中。
- 用户翻开目的网站时,网站服务端将歹意代码从数据库掏出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到相应后剖析实行,混在个中的歹意代码也被实行。
- 歹意代码盗取用户数据并发送到进击者的网站,或许假装用户的行动,挪用目的网站接口实行进击者指定的操纵。
这类进击常见于带有用户保留数据的网站功用,如论坛发帖、商品批评、用户私信等。
怎样提防存储型XSS进击:
- 前端数据通报给服务器之前,先转义/过滤(提防不了抓包修改数据的状况)
- 服务器接收到数据,在存储到数据库之前,举行转义/过滤
- 前端接收到服务器通报过来的数据,在展现到页眼前,先举行转义/过滤
除了郑重的转义,我们还须要其他一些手腕来提防XSS进击:
1.Content Security Policy
在服务端运用 HTTP的 Content-Security-Policy
头部来指定战略,或许在前端设置 meta
标签。
比方下面的设置只许可加载同域下的资本:
Content-Security-Policy: default-src 'self'
<meta http-equiv="Content-Security-Policy" content="form-action 'self';">
前端和服务端设置 CSP 的结果雷同,然则meta
没法运用report
严厉的 CSP 在 XSS 的提防中可以起到以下的作用:
- 制止加载外域代码,防备庞杂的进击逻辑。
- 制止外域提交,网站被进击后,用户的数据不会泄漏到外域。
- 制止内联剧本实行(划定规矩较严厉,现在发明 GitHub 运用)。
- 制止未受权的剧本实行(新特征,Google Map 挪动版在运用)。
- 合理运用上报可以实时发明 XSS,利于尽快修复题目。
2.输入内容长度掌握
关于不受信托的输入,都应当限定一个合理的长度。虽然没法完整防备 XSS 发作,但可以增添 XSS 进击的难度。
3.输入内容限定
关于部份输入,可以限定不能包括迥殊字符或许仅能输入数字等。
4.其他安全措施
- HTTP-only Cookie: 制止 JavaScript 读取某些敏感 Cookie,进击者完成 XSS 注入后也没法盗取此 Cookie。
- 验证码:防备剧本假装用户提交风险操纵。
12.怎样隐蔽页面中的某个元素?
隐蔽范例
屏幕并非唯一的输出机制,比方说屏幕上看不见的元素(隐蔽的元素),个中一些依旧可以被读屏软件浏览出来(由于读屏软件依赖于可接见性树来论述)。为了消弭它们之间的歧义,我们将其归为三大类:
- 完整隐蔽:元素从衬着树中消逝,不占有空间。
- 视觉上的隐蔽:屏幕中不可见,占有空间。
- 语义上的隐蔽:读屏软件不可读,但一般占有空。
完整隐蔽
1.display
属性(不占有空间)
display: none;
2.hidden 属性 (不占有空间)
HTML5 新增属性,相当于 display: none
<div hidden>
</div>
视觉上的隐蔽
1.应用 position
和 盒模子 将元素移出可视区局限
- 设置
posoition
为absolute
或fixed
,经由过程设置top
、left
等值,将其移出可视地区。(可视地区不占位)
position:absolute;
left: -99999px;
- 设置
position
为relative
,经由过程设置top
、left
等值,将其移出可视地区。(可视地区占位)
position: relative;
left: -99999px;
如愿望其在可视地区不占位置,需同时设置 height: 0
;
- 设置 margin 值,将其移出可视地区局限(可视地区占位)。
margin-left: -99999px;
假如愿望其在可视地区不占位,需同时设置 height: 0
;
2.应用 transfrom
- 缩放(占有空间)
transform: scale(0);
假如愿望不占有空间,需同时设置 height: 0
- 挪动
translateX
,translateY
(占有空间)
transform: translateX(-99999px);
假如愿望不占有空间,需同时设置 height: 0
- 扭转
rotate
(占有空间)
transform: rotateY(90deg);
3.设置其大小为0
宽高为0,字体大小为0:
height: 0;
width: 0;
font-size: 0;
宽高为0,超越隐蔽:
height: 0;
width: 0;
overflow: hidden;
4.设置透明度为0 (占有空间)
opacity: 0;
5.visibility
属性 (占有空间)
visibility: hidden
6.层级掩盖,z-index
属性 (占有空间)
position: relative;
z-index: -999;
再设置一个层级较高的元素掩盖在此元素上。
7.clip-path 裁剪 (占有空间)
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
语义上的隐蔽
aria-hidden 属性 (占有空间)
读屏软件不可读,占有空间,可见。
<div aria-hidden="true">
</div>
11. 运用JS将元素从页面中移除
13.浏览器事宜代办机制的道理是什么?
事宜流
在说浏览器事宜代办机制道理之前,我们起首相识一下事宜流的观点,初期浏览器,IE采纳的是事宜捕捉事宜流,而Netscape采纳的则是事宜冒泡。”DOM2级事宜”把事宜流分为三个阶段,捕捉阶段、目的阶段、冒泡阶段。当代浏览器也都遵照此范例。
事宜代办机制的道理
事宜代办又称为事宜托付,在先人级 DOM 元素绑定一个事宜,当触发子孙级DOM元素的事宜时,应用事宜冒泡的道理来触发绑定在先人级 DOM 的事宜。由于事宜会从目的元素一层层冒泡至 document 对象。
为何要事宜代办?
- 增添到页面上的事宜数目会影响页面的运转机能,假如增添的事宜过量,会致使网页的机能下落。采纳事宜代办的体式格局,可以大大削减注册事宜的个数。
- 事宜代办的当时,某个子孙元素是动态增添的,不须要再次对其举行事宜绑定。
- 不必忧郁某个注册了事宜的DOM元素被移除后,能够没法接纳其事宜处置惩罚顺序,我们只要把事宜处置惩罚顺序托付给更高层级的元素,就可以防备此题目。
- 许可给一个事宜注册多个监听。
- 供应了一种更邃密的手腕掌握
listener
的触发阶段(可以挑选捕捉或许是冒泡)。 - 对任何
DOM
元素都是有用的,而不仅仅是对HTML
元素有用。
addEventListener
addEventListener 接收3个参数,分别是要处置惩罚的事宜名、完成了 EventListener 接口的对象或许是一个函数、一个对象/一个布尔值。
target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
options(对象) | 可选
- capture:
Boolean
。true 示意在捕捉阶段触发,false示意在冒泡阶段触发。默许是 false。 - once:
Boolean
。true 示意listener 在增添以后最多只挪用一次,listener 会在其被挪用以后自动移除。默许是 false。 - passive:
Boolean
。true 示意 listener 永久不会挪用preventDefault()
。假如 listener 依然挪用了这个函数,客户端将会疏忽它并抛出一个掌握台正告。默许是 false。
useCapture(Boolean) | 可选
useCapture
默许为 false。示意冒泡阶段挪用事宜处置惩罚顺序,若设置为 true,示意在捕捉阶段挪用事宜处置惩罚顺序。
如将页面中的一切click事宜都代办到document上:
document.addEventListener('click', function (e) {
console.log(e.target);
/**
* 捕捉阶段挪用挪用事宜处置惩罚顺序,eventPhase是 1;
* 处于目的,eventPhase是2
* 冒泡阶段挪用事宜处置惩罚顺序,eventPhase是 3;
*/
console.log(e.eventPhase);
}, false);
与 addEventListener
相对应的是 removeEventListener
,用于移除事宜监听。
14. setTimeout 倒计时为何会涌现偏差?
setTimeout
只能保证延时或距离不小于设定的时候。由于它实际上只是将回调增添到了宏使命行列中,然则假如主线程上有使命还没有实行完成,它必需要守候。
假如你对前面这句话不是异常明白,那末有必要相识一下 JS的运转机制。
JS的运转机制
(1)一切同步使命都在主线程上实行,构成一个实行栈(execution context stack)。
(2)主线程以外,还存在”使命行列”(task queue)。
(3)一旦”实行栈”中的一切同步使命实行终了,体系就会读取”使命行列”,看看内里有哪些事宜。那些对应的异步使命,因而完毕守候状况,进入实行栈,最先实行。
(4)主线程不停反复上面的第三步。
如 setTimeout(()=>{callback();}, 1000)
,即示意在1s以后将 callback
放到宏使命行列中,当1s的时候抵达时,假如主线程上有别的使命在实行,那末 callback
就必需要守候,别的 callback
的实行也须要时候,因而 setTimeout
的时候距离是有偏差的,它只能保证延时不小于设置的时候。
怎样削减 setTimeout
的偏差
我们只能削减实行屡次的 setTimeout
的偏差,比方倒计时功用。
倒计时的时候一般都是从服务端猎取的。形成偏差的缘由:
1.没有斟酌偏差时候(函数实行的时候/别的代码的壅塞)
2.没有斟酌浏览器的“休眠”
完整消弭 setTimeout
的偏差是不能够的,然则我们削减 setTimeout
的偏差。经由过程对下一次使命的挪用时候举行修改,来削减偏差。
let count = 0;
let countdown = 5000; //服务器返回的倒计时时候
let interval = 1000;
let startTime = new Date().getTime();
let timer = setTimeout(countDownStart, interval); //初次实行
//定时器测试
function countDownStart() {
count++;
const offset = new Date().getTime() - (startTime + count * 1000);
const nextInterval = interval - offset; //修改后的延时时候
if (nextInterval < 0) {
nextInterval = 0;
}
countdown -= interval;
console.log("偏差:" + offset + "ms,下一次实行:" + nextInterval + "ms后,离运动最先另有:" + countdown + "ms");
if (countdown <= 0) {
clearTimeout(timer);
} else {
timer = setTimeout(countDownStart, nextInterval);
}
}
假如当前页面是不可见的,那末倒计时会涌现大于100ms的偏差时候。因而在页面显现时,应当从新从服务端猎取剩余时候举行倒计时。固然,为了更好的机能,当倒计时不可见(Tab页切换/倒计时内容不在可视区时),可以挑选住手倒计时。
为此,我们可以监听 visibityChange
事宜举行处置惩罚。
参考文章:
[2] https://www.ecma-internationa…
[3] http://www.xuanfengge.com/js-…
感谢列位小伙伴情愿消费珍贵的时候浏览本文,假如本文给了您一点协助或许是启示,请不要悭吝你的赞和Star,您的肯定是我行进的最大动力。https://github.com/YvetteLau/…
关注民众号,到场技术交流群。