例如下面的配置只允许加载同域下的资源:

  1. Content-Security-Policy: default-src 'self'

  1. <meta http-equiv="Content-Security-Policy" content="form-action 'self';">

前端和服务端设置 CSP 的效果相同,但是meta无法使用report

严格的 CSP 在 XSS 的防范中可以起到以下的作用:

禁止加载外域代码,防止复杂的攻击逻辑。

禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。

禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。

禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。

合理使用上报可以及时发现 XSS,利于尽快修复问题。

2.输入内容长度控制

对于不受信任的输入,都应该限定一个合理的长度。虽然无法完全防止 XSS 发生,但可以增加 XSS 攻击的难度。

3.输入内容限制

对于部分输入,可以限定不能包含特殊字符或者仅能输入数字等。

4.其他安全措施

12.如何隐藏页面中的某个元素?隐藏类型

屏幕并不是唯一的输出机制,比如说屏幕上看不见的元素(隐藏的元素),其中一些依然能够被读屏软件阅读出来(因为读屏软件依赖于可访问性树来阐述)。为了消除它们之间的歧义,我们将其归为三大类:

完全隐藏1.display属性(不占据空间)

  1. display: none;

2.hidden 属性 (不占据空间)

HTML5 新增属性,相当于display:none

  1. <div hidden>

视觉上的隐藏1.利用position和 盒模型 将元素移出可视区范围

设置posoition为absolute或fixed,通过设置top、left等值,将其移出可视区域。(可视区域不占位)

  1. position:absolute;

  2. left: -99999px;

设置position为relative,通过设置top、left等值,将其移出可视区域。(可视区域占位)

  1. position: relative;

  2. left: -99999px;

如希望其在可视区域不占位置,需同时设置height:0;

设置 margin 值,将其移出可视区域范围(可视区域占位)。

  1. margin-left: -99999px;

如果希望其在可视区域不占位,需同时设置height:0;

2.利用 transfrom

缩放(占据空间)

  1. transform: scale(0);

如果希望不占据空间,需同时设置height:0

移动translateX,translateY(占据空间)

  1. transform: translateX(-99999px);

如果希望不占据空间,需同时设置height:0

旋转rotate(占据空间)

  1. transform: rotateY(90deg);

3.设置其大小为0

宽高为0,字体大小为0:

  1. height: 0;

  2. width: 0;

  3. font-size: 0;

宽高为0,超出隐藏:

  1. height: 0;

  2. width: 0;

  3. overflow: hidden;

4.设置透明度为0 (占据空间)

  1. opacity: 0;

5.visibility属性 (占据空间)

  1. visibility: hidden

6.层级覆盖,z-index属性 (占据空间)

  1. position: relative;

  2. z-index: -999;

再设置一个层级较高的元素覆盖在此元素上。

7.clip-path 裁剪 (占据空间)

  1. clip-path: polygon(0 0, 0 0, 0 0, 0 0);

语义上的隐藏aria-hidden 属性 (占据空间)

读屏软件不可读,占据空间,可见。

  1. <div aria-hidden="true">

11. 使用JS将元素从页面中移除13.浏览器事件代理机制的原理是什么?事件流

在说浏览器事件代理机制原理之前,我们首先了解一下事件流的概念,早期浏览器,IE采用的是事件捕获事件流,而Netscape采用的则是事件冒泡。”DOM2级事件”把事件流分为三个阶段,捕获阶段、目标阶段、冒泡阶段。现代浏览器也都遵循此规范。

ariahidden属性_ariahidden什么意思_aria-hidden

事件代理机制的原理

事件代理又称为事件委托,在祖先级 DOM 元素绑定一个事件,当触发子孙级DOM元素的事件时,利用事件冒泡的原理来触发绑定在祖先级 DOM 的事件。因为事件会从目标元素一层层冒泡至 document 对象。

为什么要事件代理?

添加到页面上的事件数量会影响页面的运行性能,如果添加的事件过多,会导致网页的性能下降。采用事件代理的方式,可以大大减少注册事件的个数。

事件代理的当时,某个子孙元素是动态增加的,不需要再次对其进行事件绑定。

不用担心某个注册了事件的DOM元素被移除后,可能无法回收其事件处理程序,我们只要把事件处理程序委托给更高层级的元素,就可以避免此问题。

允许给一个事件注册多个监听。

提供了一种更精细的手段控制listener的触发阶段(可以选择捕获或者是冒泡)。

对任何DOM元素都是有效的,而不仅仅是对HTML元素有效。

addEventListener

addEventListener 接受3个参数,分别是要处理的事件名、实现了 EventListener 接口的对象或者是一个函数、一个对象/一个布尔值。

  1. target.addEventListener(type, listener[, options]);

  2. target.addEventListener(type, listener[, useCapture]);

options(对象) | 可选

useCapture(Boolean) | 可选

useCapture默认为 false。表示冒泡阶段调用事件处理程序,若设置为 true,表示在捕获阶段调用事件处理程序。

如将页面中的所有click事件都代理到document上:

  1. document.addEventListener('click', function (e) {

  2. console.log(e.target);

  3. /**

  4. * 捕获阶段调用调用事件处理程序,eventPhase是 1;

  5. * 处于目标,eventPhase是2

  6. * 冒泡阶段调用事件处理程序,eventPhase是 3;

  7. */

  8. console.log(e.eventPhase);


  9. }, 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的误差。通过对下一次任务的调用时间进行修正,来减少误差。

  1. let count = 0;

  2. let countdown = 5000; //服务器返回的倒计时时间

  3. let interval = 1000;

  4. let startTime = new Date().getTime();

  5. let timer = setTimeout(countDownStart, interval); //首次执行

  6. //定时器测试

  7. function countDownStart() {

  8. count++;

  9. const offset = new Date().getTime() - (startTime + count * 1000);

  10. const nextInterval = interval - offset; //修正后的延时时间

  11. if (nextInterval < 0) {

  12. nextInterval = 0;

  13. }

  14. countdown -= interval;

  15. console.log("误差:" + offset + "ms,下一次执行:" + nextInterval + "ms后,离活动开始还有:" + countdown + "ms");

  16. if (countdown <= 0) {

  17. clearTimeout(timer);

  18. } else {

  19. timer = setTimeout(countDownStart, nextInterval);

  20. }

  21. }

如果当前页面是不可见的,那么倒计时会出现大于100ms的误差时间。因此在页面显示时,应该重新从服务端获取剩余时间进行倒计时。当然,为了更好的性能,当倒计时不可见(Tab页切换/倒计时内容不在可视区时),可以选择停止倒计时。

为此,我们可以监听visibityChange事件进行处理。

参考文章:

[1]MDN addEventListener

[2] #sec-completion-record-specification-type

[3]

谢谢各位小伙伴愿意花费宝贵的时间阅读本文,如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和Star,您的肯定是我前进的最大动力。

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注