【Step-By-Step】深度解析本周面试题-Weekly03
时间:2023-04-05 13:15:07
HTML5
本周面试题一览:什么是XSS攻击,XSS攻击分为哪几类?我们如何防范XSS攻击?如何隐藏页面中的元素?浏览器事件代理机制的原理是什么?为什么setTimeout倒计时会出错?11、什么是XSS攻击,XSS攻击分为哪几类?我们如何防范XSS攻击?1、XSS攻击XSS(Cross-SiteScripting,跨站脚本攻击)是一种代码注入攻击。攻击者在目标网站注入恶意代码,当受害者登录网站时恶意代码就会被执行。这些脚本可以读取cookies、sessiontoken或其他网站敏感信息,钓鱼和欺诈用户,甚至发动蠕虫攻击等。XSS的本质是恶意代码不被过滤,与网站正常代码混合;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。由于直接在用户终端执行,恶意代码可以直接获取用户信息,并利用这些信息冒充用户向网站发起攻击者自定义请求。XSS分类根据攻击来源,XSS攻击可分为存储型(持久型)、反射型(非持久型)和DOM型三种。下面我们来详细了解一下这三种类型的XSS攻击:1.1ReflectedXSS当用户点击恶意链接,或者提交表单,或者进入恶意网站时,注入的脚本就会进入受害者的网站。网络服务器会注入脚本,如错误信息、搜索结果等,不经过滤直接返回给用户浏览器。反射型XSS攻击步骤:攻击者构造一个包含恶意代码的特殊URL。当用户打开带有恶意代码的URL时,网站服务器会从该URL中提取恶意代码,拼接成HTML返回给浏览器。用户浏览器收到响应后,解析并执行,其中混入的恶意代码也被执行。恶意代码窃取用户数据并发送到攻击者网站,或冒充用户调用目标网站的接口执行攻击者指定的操作。反射型XSS漏洞常见于通过URL传递参数的功能,例如网站搜索和重定向。由于需要用户主动打开恶意网址才能生效,因此攻击者往往会结合多种手段诱导用户点击。POST的内容也可以触发反射型XSS,但是触发条件比较苛刻(需要构建表单提交页面,引导用户点击),所以很少见。如果不想让前端获取到cookie,后端可以设置httpOnly(但这不是XSS攻击的解决方案,只能减少危害范围)。如何防止反射XSS攻击对字符串进行编码。在输出到页面之前对url的查询参数进行转义。app.get('/welcome',function(req,res){//编码查询参数以避免反射型XSS攻击res.send(`${encodeURIComponent(req.query.type)}`);});1.2DOM-typeXSSDOM型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,我们可以这样编码:functionencodeHtml(str){returnstr.replace(/"/g,'"').replace(/'/g,''').replace(//g,'>');}DOM型XSS攻击,恶意代码的提取和执行由浏览器完成,是前端JavaScript本身的安全漏洞.1.3存储型XSS恶意脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器传回并执行,影响范围比反射型和DOM型XSS大。存储型XSS攻击的原因还是数据过滤没做好:前端向服务端提交数据时,没有做好过滤;服务器接收到数据时,在存储数据之前不进行过滤;前端向服务器请求数据,不过滤输出。存储型XSS攻击步骤:攻击者向目标网站的数据库提交恶意代码。当用户打开目标网站时,网站服务器会从数据库中取出恶意代码,拼接成HTML返回给浏览器。用户浏览器收到响应后,解析并执行,其中混入的恶意代码也被执行。恶意代码窃取用户数据并发送到攻击者网站,或冒充用户调用目标网站的接口执行攻击者指定的操作。这种攻击常见于有用户保存数据的网站功能,如论坛帖子、产品评论、用户私信等。如何防止存储型XSS攻击:前端数据传到服务器前,先转义/过滤(不能防止数据被抓取修改)。服务端收到数据,在存入数据库之前,进行转义/过滤。传入的数据应该在显示在页面上之前进行转义/过滤。除了小心转义之外,我们还需要一些其他的手段来防止XSS攻击:1.ContentSecurityPolicy在server端部分使用HTTP的Content-Security-Policy头来指定策略,或者在前端设置meta标签。例如下面的配置只允许加载同域下的资源:Content-Security-Policy:default-src'self'在前端和服务端设置CSP的效果是一样的,但是meta不能使用report。StrictCSP在XSS防御中可以起到以下作用:禁止加载外域代码,防止复杂的攻击逻辑。禁止从外部域提交。网站被攻击后,用户数据不会泄露到外域。禁用内联脚本执行(规则更严格,目前可在GitHub中找到)。防止未经授权的脚本执行(谷歌手机地图正在使用的新功能)。合理使用上报可以及时发现XSS,有利于尽快修复问题。2.输入内容长度控制对于不可信的输入,应该限制一个合理的长度。XSS虽然不能完全杜绝,但是可以增加XSS攻击的难度。3.输入内容限制对于某些输入,您可以限制不能包含特殊字符或只能输入数字。4.其他安全措施HTTP-onlyCookie:禁止JavaScript读取某些敏感cookie,攻击者完成XSS注入后无法窃取此cookie。Captcha:防止脚本冒充用户提交危险操作。点击查看更多12、如何隐藏页面中的某个元素?隐藏类型屏幕不是唯一的输出机制,例如屏幕上的不可见元素(隐藏元素),其中一些仍然可以被屏幕阅读器阅读(因为屏幕阅读器依赖可访问性树来说明)。为了消除歧义,我们将它们分为三大类:完全隐藏:元素从渲染树中消失,不占用空间。Visuallyhidden:在屏幕上不可见,占用空间。语义隐藏:屏幕阅读器无法读取,但通常会占用空间。完全隐藏1.display属性(不占空间)display:none;2.hidden属性(不占空间)HTML5新属性,相当于display:none
可视化隐藏1.使用positionAnd盒子模型将元素移出可见区域。设置position为absolute或fixed,通过设置top、left等值将其移出可见区域。(可见区域不占空间)position:absolute;left:-99999px;设置position为relative,通过设置top、left等值将其移出可见区域。(占用可见区域)position:relative;左:-99999px;如果想让它在可见区域不占位置,需要同时设置height:0;设置margin值使其移出可见区域(可见区域占bits)。左边距:-99999px;如果想让它不占用可见区域的空间,需要同时设置height:0;2.使用transfrom进行缩放(占用空间)transform:scale(0);如果想让它不占用空间,需要同时设置height:0movetranslateX,translateY(占用空间)transform:translateX(-99999px);如果不想占用空间,需要设置height:0rotaterotate(占用空间)transform:rotateY(90deg);3.设置它的size为0宽和高都是0,字体大小是0:height:0;宽度:0;字体大小:0;width和height都为0,超出hidden:height:0;宽度:0;溢出:隐藏;4.设置透明度为0(占用空间)opacity:0;5.visibility属性(占空间)visibility:hidden6.levelcoverage,z-index属性(占空间)position:relative;z-指数:-999;设置一个更高级别的元素覆盖这个元素。7.clip-path裁剪(占用空间)clip-path:polygon(00,00,00,00);语义隐藏的aria-hidden属性(占用空间)屏幕阅读器软件无法读取,占用空间,可见。
11。使用JS从页面中删除元素。点击查看更多13、浏览器事件代理机制的原理是什么?事件流在谈浏览器事件代理机制的原理之前,我们先了解一下事件流的概念。在早期的浏览器中,IE使用的是事件捕获事件流,而Netscape使用的是事件冒泡。“DOM2级事件”将事件流分为三个阶段,捕获阶段、目标阶段和冒泡阶段。现代浏览器也遵循这个规范。事件代理机制原理事件代理也称为事件委托。事件绑定到祖先DOM元素。当触发后代DOM元素的事件时,利用事件冒泡的原理触发绑定到祖先DOM上的事件。因为事件会从目标元素逐层冒泡到文档对象。为什么是事件代理?添加到页面的事件数量会影响页面的运行性能。如果添加过多的事件,网页的性能会下降。使用事件代理的方式可以大大减少注册事件的数量。在事件代理的时候,动态添加了某个后代元素,不需要再对其进行事件绑定。不用担心注册了事件的DOM元素被移除后,它的事件处理程序可能不会被回收。我们可以通过将事件处理程序委托给更高级别的元素来避免这个问题。允许为一个事件注册多个侦听器。提供更细粒度的手段来控制监听器的触发阶段(可以选择捕获或冒泡)。适用于任何DOM元素,而不仅仅是HTML元素。addEventListeneraddEventListener接受3个参数,分别是要处理的事件名称,一个实现了EventListener接口或函数的对象,一个对象/一个布尔值。target.addEventListener(type,listener[,options]);target.addEventListener(type,listener[,useCapture]);options(object)|可选捕获:布尔值。true表示在捕获阶段触发,false表示在冒泡阶段触发。默认为假。一次:布尔值。true表示监听器添加后最多只调用一次,调用后自动移除监听器。默认为假。被动:布尔值。true表示侦听器永远不会调用preventDefault()。如果侦听器仍然调用此函数,客户端将忽略它并抛出控制台警告。默认为假。useCapture(布尔)|可选的useCapture默认为false。表示在冒泡阶段调用事件处理程序,如果设置为true,则表示在捕获阶段调用事件处理程序。比如页面中所有的点击事件都委托给文档:document.addEventListener('click',function(e){console.log(e.target);/***捕获阶段调用call事件处理函数,eventPhase为1;*在目标处,eventPhase为2*在冒泡阶段调用事件处理器,eventPhase为3;*/console.log(e.eventPhase);},false);对应的addEventListener为removeEventListener,用于移除Event监听器。点击查看更多14.为什么setTimeout倒计时有错误?setTimeout只能保证延时或者间隔不小于设置的时间。因为它其实只是把回调加入到宏任务队列中,但是如果主线程上有任务没有执行完,就得等待。如果对前面那句话不是很理解,那么了解JS的运行机制是很有必要的。JS的运行机制(1)所有同步任务都在主线程上执行,形成一个执行上下文栈(executioncontextstack)。(2)除了主线程之外,还有一个“任务队列”。(3)一旦“执行栈”中的所有同步任务都执行完毕,系统就会去读取“任务队列”,看看里面有什么事件。那些对应的异步任务结束等待状态,进入执行栈,开始执行。(4)主线程不断重复上面的第三步。如setTimeout(()=>{callback();},1000),表示回调1s后放入宏任务队列。当1s的时间到了,如果主线程还有其他任务在执行,那么callback就得等待,callback的执行也需要时间,所以setTimeout的时间间隔有误差,只能保证延迟不小于设定时间。如何减少setTimeout的误差我们只能减少setTimeout多次执行的误差,比如倒计时函数。倒计时时间通常从服务器获取。报错原因:1.没有考虑报错时间(函数执行时间/阻塞其他代码)2.不考虑浏览器“休眠”是不可能完全消除setTimeout报错的,但是我们减少了报错设置超时。通过更正下一个任务的调用时间来减少错误。让计数=0;让倒计时=5000;//服务器返回的倒计时时间letinterval=1000;letstartTime=newDate().getTime();lettimer=setTimeout(countDownStart,interval);//第一次执行//定时器测试函数countDownStart(){count++;constoffset=newDate().getTime()-(startTime+count*1000);constnextInterval=间隔-偏移量;//修正延迟时间if(nextInterval<0){nextInterval=0;}倒计时-=间隔;console.log("错误:"+offset+"ms,下次执行:"+nextInterval+"ms,距离活动开始还有时间:"+countdown+"ms");如果(倒计时<=0){clearTimeout(定时器);}else{timer=setTimeout(countDownStart,nextInterval);}}如果当前页面不可见,倒计时会出现大于100ms的错误时间。因此,当页面显示时,需要再次从服务器获取剩余时间进行倒计时。当然,为了更好的性能,当倒计时不可见时(Tab页切换/倒计时内容不在可见区域),可以选择停止倒计时。为此,我们可以监听visibilityChange事件进行处理。点击查看更多参考文章:[1]MDNaddEventListener[2]https://www.ecma-internationala...[3]http://www.xuanfengge.com/js-...谢谢大家的支持愿意花宝贵的时间阅读本文。如果这篇文章能给你一点帮助或者启发,请不要吝啬你的点赞和star。您的肯定是我前进的最大动力。https://github.com/YvetteLau/...推荐关注我公众号: