浏览器原理二三事

目录

1. 如何理解 JavaScript 是单线程的

2. 进程与线程

2.1 在浏览器中,如何理解进程和线程的关系?

2.2 浏览器的五种进程

2.2.1 浏览器主进程(Browser 进程)

2.2.2 浏览器渲染进程(Renderer 进程)

2.2.3 GPU 进程

2.2.4 第三方插件进程

2.2.5 网络进程

2.3 浏览器渲染进程(Renderer 进程)包含的五种线程

2.3.1 GUI 渲染线程

2.3.2 JavaScript 引擎线程

2.3.3 事件触发线程

2.3.4 定时器触发线程

2.3.5 异步http请求线程

2.4 Chrome 打开一个页面需要启动多少进程?

3. script 标签上的 async、defer

3.1 为什么要使用 async、defer

3.2 async、defer 的区别

3.2.1 执行顺序的区别

3.2.2 使用场景的区别

3.2.3 window.onload 执行顺序的区别

4. DOM 事件流(事件执行顺序)

4.1 事件流的基本概念

4.2 事件委托(利用事件冒泡的原理)

4.3 addEventListener 的第三个参数

4.4 事件流的执行顺序(先捕获再冒泡)

5. 浏览器空闲时间

5.1 浏览器一帧内做了什么

5.2 requestIdleCallback

6. 浏览器缓存

6.1 协商缓存(Etag、Last-Modified)

6.1.1 协商缓存基本过程

6.1.2 Etag VS Last-Modified

6.2 强制缓存(Expires、Cache-Control)

6.2.1 Cache-Control VS Expires

6.2.2 Cache-Control: no-cache VS Cache-Control: no-store

7. 垃圾回收机制

7.1 GC 垃圾回收策略

7.1.1 标记清除

7.1.2 引用计数

7.2 分代式垃圾回收机制

7.2.1 新生代的垃圾回收方式

7.2.2 老生代的垃圾回收方式

7.2.3 新老生代在不同系统的内存大小

7.3 垃圾回收机制参考文章


1. 如何理解 JavaScript 是单线程的

JavaScript 是单线程的:

  • 只是说 JavaScript 的执行是单线程的
  • 但 JavaScript 的宿主环境(Node 或者 浏览器),都是多线程的

JavaScript 设计为单线程的原因:

  • 如果有多个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时就存在冲突
  • 为了避免冲突,JavaScript 就设计成了单线程的

2. 进程与线程

浏览器的线程和进程 - 简书前言 学习真的是一个很奇妙的过程。本意是学习状态管理工具Redux,其中涉及到Promise异步编程知识,发现不太熟悉,于是决定先学学Promise相关知识。Promise文...https://www.jianshu.com/p/c1808d0c1d45

2.1 在浏览器中,如何理解进程和线程的关系?

以 Chrome 浏览器为例:

  • 当打开了一个页面时,其实就创建了一个进程
  • 一个进程中可以有多个线程,比如渲染线程、JS 引擎线程、HTTP 请求线程等
  • 当发起一个请求时,其实就创建了一个线程;当请求结束时,该线程就会被销毁
  • 进程是 CPU 资源分配的最小单位;线程是 CPU 调度的最小单位

为什么浏览器是多进程的?

  • 对于简单的网页,一个进程处理多个网页是可行的;但是如果把 多个 复杂的网页放进一个进程,一个 Tab 页崩溃,将导致同进程的其他页面崩溃,极其影响用户体验
  • 进程之间 不共享 资源和地址空间,所以使用多个进程,可以避免更多的安全问题;多进程相对于单进程,内存等资源消耗更大,有点空间换时间的意思;这大概也是浏览器中存在多个 Tab 页时共用一个进程的原因吧

2.2 浏览器的五种进程

打开 Google 中的任务管理器(Shift + Esc 或者 Chrome 更多工具 → 任务管理器)

可以看到展现了四种进程:

  • 浏览器主进程
  • GPU 进程
  • 第三方插件进程
  • 浏览器渲染进程

2.2.1 浏览器主进程(Browser 进程)

只有一个主进程,主要负责:

  • 界面显示
  • 用户交互(前进后退)
  • 子进程管理(创建/销毁其他进程)
  • 将 Renderer 进程得到的 内存中的 Bitmap,绘制到用户界面上
  • 提供存储、下载、网络资源管理等

2.2.2 浏览器渲染进程(Renderer 进程)

就是通常所说的浏览器内核,排版引擎 Blink 和 JavaScript 引擎 V8 都运行在该进程中

核心任务:将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页(实现 —— 页面渲染、脚本执行、事件处理等)

出于安全考虑,渲染进程都是运行在沙箱模式下

默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程,互不影响;存在多个标签页时,会自动合并进程

2.2.3 GPU 进程

GPU 的使用初衷是为了实现 3D CSS 的效果

只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制

GPU 进程可以禁用,只有一个 GPU 进程

2.2.4 第三方插件进程

主要是负责插件的运行每种类型的插件,对应一个进程

因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响

2.2.5 网络进程

主要负责页面的网络资源加载

之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程

2.3 浏览器渲染进程(Renderer 进程)包含的五种线程

前面说过,Renderer 进程的核心任务:将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页(实现 —— 页面渲染、脚本执行、事件处理等)

2.3.1 GUI 渲染线程

主要负责页面的渲染,解析 HTML、CSS,构建 DOM 树,布局和绘制等

当界面需要重绘(Repaint)或 由于某种操作 引发回流(reflow)时,该线程就会执行

2.3.2 JavaScript 引擎线程

该线程主要负责处理 JavaScript 脚本,执行代码

一个 Tab 页(Renderer进程)中,无论什么时候,都只有一个 JavaScript  线程在运行 JavaScript  程序

该线程与 GUI 渲染线程互斥,当 JavaScript  引擎线程执行 JavaScript 脚本时间过长,将导致页面渲染的阻塞

2.3.3 事件触发线程

用来控制事件循环,将准备好的事件交给 JavaScript 引擎线程执行

事件触发线程不属于 JavaScript 引擎线程,而是属于浏览器(JavaScript 引擎线程自己忙不过来,需要浏览器再开一个线程协助他)

比如 setTimeout 定时器计数结束, ajax 等异步请求成功并触发回调函数,或者用户触发点击事件时,该线程会将整装待发的事件,依次加入到任务队列的队尾,等待 JavaScript 引擎线程的执行

2.3.4 定时器触发线程

负责执行异步定时器一类的函数的线程,如: setTimeout,setInterval

浏览器定时计数器,并不是由 JavaScript 引擎计数的,因为 JavaScript 引擎是单线程的,如果处于阻塞线程状态,就会影响记计时的准确性

2.3.5 异步http请求线程

负责执行异步请求一类的函数的线程,如: Promise,axios,ajax 等

2.4 Chrome 打开一个页面需要启动多少进程?

浏览器从关闭状态进行启动,然后新开 1 个页面,至少需要 1 个网络进程、1 个浏览器进程、1 个 GPU 进程以及 1 个渲染进程,共 4 个进程;

后续再新开标签页,浏览器、网络进程、GPU进程是共享的,不会重新启动;

如果2个页面属于同一站点的话,并且从a页面中打开的b页面,那么他们也会共用一个渲染进程,否则新开一个渲染进程

                                     

                                                                                     ——  《浏览器工作原理与实践》

最新的 Chrome 浏览器包括:1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、多个渲染进程和多个插件进程。

浏览器相关原理(面试题)详细总结一 - 掘金1. Chrome 打开一个页面需要启动多少进程?分别有哪些进程? 浏览器从关闭状态进行启动,然后新开 1 个页面至少需要 1 个网络进程、1 个浏览器进程、1 个 GPU 进程以及 1 个渲染进程,共 4 个进程;后续再新开标签页,浏览器、网络进程、GPU进程是共享的,不会重…https://juejin.cn/post/6844903962216824839#heading-0

3. script 标签上的 async、defer

3.1 为什么要使用 async、defer

先来谈一下浏览器的渲染机制:浏览器有 GUI 渲染线程与 JavaScript 引擎线程,这两个线程是互斥的关系

JavaScrip t的加载、解析与执行会阻塞 DOM 的构建。也就是说,在构建 DOM 时,HTML 解析器若遇到了JavaScript,那么它会暂停构建 DOM,将控制权移交给 JavaScript 引擎,等 JavaScript 引擎运行完毕,浏览器再从中断的地方恢复DOM构建

综上所述,直接使用 script 标签,会阻塞 DOM 渲染;但如果使用带有 async 和 defer 的 script 标签,就会异步请求这些资源,不会阻塞页面渲染

浏览器渲染过程分为:构建DOM -> 构建CSSOM -> 构建渲染树 -> layout布局 -> 绘制

3.2 async、defer 的区别

记忆要点:

  • defer 有顺序,async 没顺序
  • defer 在 window.onload 之前,async 都有可能

浅谈script标签中的async和defer - 贾顺名 - 博客园script标签用于加载脚本与执行脚本,在前端开发中可以说是非常重要的标签了。直接使用script脚本的话,html会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM渲染https://www.cnblogs.com/jiasm/p/7683930.html

3.2.1 执行顺序的区别

async 是无顺序的加载,而 defer 是有顺序的加载

async 的执行,并不会按照 script 在页面中的顺序来执行,而是谁先加载完谁执行

defer 的执行,则会按照引入的顺序执行,即便是后面的 script 资源先返回

3.2.2 使用场景的区别

defer 可以用来控制 JavaScript 文件的加载顺序;比如 jqery 和 Bootstrap,因为 Bootstrap 中的 JavaScript 插件依赖于 jqery,所以必须先引入jquery,再引入 Bootstrap 文件

如果你的脚本并不关心页面中的 DOM 元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据,使用 async, 如统计、埋点等功能

3.2.3 window.onload 执行顺序的区别

使用 defer 的 script 标签,会在 window.onload 事件之前被执行

使用 async 的 script 标签,对 window.onload 事件没有影响,window.onload 可以在之前或之后执行

4. DOM 事件流(事件执行顺序)

4.1 事件流的基本概念

DOM 同时支持两种事件模型:

  • 捕获型事件流
  • 冒泡型事件流

DOM 事件流的三个阶段:

  • 事件捕获阶段
  • 处于目标阶段
  • 事件冒泡阶段

DOM 事件捕获 的具体流程:window➡️document➡️html➡️body➡️目标元素;

DOM 事件冒泡 的具体流程:目标元素➡️body➡️html➡️document➡️window;

4.2 事件委托(利用事件冒泡的原理)

事件委托的原理:

  •  一组元素 要添加相同的事件时,可以在父元素上绑定一个事件,利用事件冒泡,达到父元素代理子元素事件
  • 点击子元素,通过 e.target || e.srcElement 可以获取点击的具体子元素

事件委托优点:可以减少事件的注册,节省内存;也可以实现新增对象时,无需再次绑定事件

4.3 addEventListener 的第三个参数

第三个参数默认是 false,表示在 事件冒泡 阶段调用;

第三个参数值为 true 时,表示在 事件捕获 阶段调用;

4.4 事件流的执行顺序(先捕获再冒泡)

// 鼠标点击子元素后,打印顺序为
// 父捕获
// 子捕获
// 子冒泡
// 父冒泡

<html>
  <div class="parent">
    <div class="child">子元素</div>
  </div>

  <script>
     let parentDom = document.querySelector('.parent');
     parentDom.addEventListener('click', function () {console.log('父捕获'); }, true)
     parentDom.addEventListener('click', function () {console.log('父冒泡');}, false)

     let childDom = document.querySelector('.child')
     childDom.addEventListener('click', function () {console.log('子捕获');}, true)
     childDom.addEventListener('click', function () {console.log('子冒泡');}, false)
  </script>
</html>

5. 浏览器空闲时间

页面是一帧一帧绘制出来的,一般情况下,设备的屏幕刷新率为 1s 60次,而当 FPS 小于 60 时,会出现一定程度的卡顿现象

5.1 浏览器一帧内做了什么

首先需要处理输入事件,能够让用户得到最早的反馈

接下来是处理定时器,需要检查定时器是否到时间,并执行对应的回调

接下来处理 Begin Frame(开始帧),即每一帧的事件,包括 window.resize、scroll、media、query、change 等

接下来执行请求动画帧 requestAnimationFrame(rAF),即在每次绘制之前,会执行 rAF 回调

紧接着进行 Layout 操作,包括计算布局和更新布局,即这个元素的样式是怎样的,它应该在页面如何展示

接着进行 Paint 操作,得到树中每个节点的尺寸与位置等信息,浏览器针对每个元素进行内容填充

到这时以上的六个阶段都已经完成了,接下来处于空闲阶段(Idle Peroid)

5.2 requestIdleCallback

在空闲阶段(Idle Peroid)时,可以执行 requestIdleCallback 里注册的任务

requestIdleCallback 接受了两个参数:

window.requestIdleCallback(callback, { timeout: 1000 })

 

1)第一个参数是一个函数,该函数的入参,可以获取:

  • 当前帧的剩余时间
  • 该任务是否超时
window.requestIdleCallback(deadline => {
  // 返回当前帧还剩多少时间供用户使用
  deadline.timeRamining;
  // 返回 callback 任务是否超时
  deadline.didTimeout;
});

 

2)第二个参数,传入 timeout 参数自定义超时时间,如果到了超时时间,浏览器必须立即执行

// 该函数的执行时间超过1s
function calc() {
  let start = performance.now();
  let sum = 0;
  for (let i = 0; i < 10000; i++) {
    for (let i = 0; i < 10000; i++) {
      sum += Math.random();
    }
  }
  let end = performance.now();
  let totolTime = end - start;
  // 得到该函数的计算用时
  console.log(totolTime, "totolTime");
}

let tasks = [
  () => {
    calc();
    console.log(1);
  },
  () => {
    calc();
    console.log(2);
  },
  () => {
    console.log(3);
  }
];

let work = deadline => {
  console.log(`此帧的剩余时间为: ${deadline.timeRemaining()}`);

  // 如果此帧剩余时间大于0,或者已经到了定义的超时时间(上文定义了timeout时间为1000,到达时间时必须强制执行),且当时存在任务,则直接执行这个任务
  // 如果没有剩余时间,则应该放弃执行任务控制权,把执行权交还给浏览器
  while (
    (deadline.timeRemaining() > 0 || deadline.didTimeout) &&
    tasks.length > 0
  ) {
    let fn = tasks.shift();
    fn();
  }
  // 如果还有未完成的任务,继续调用 requestIdleCallback 申请下一个时间片
  if (tasks.length > 0) {
    window.requestIdleCallback(work, { timeout: 500 });
  }
};

window.requestIdleCallback(work, { timeout: 500 });

打印结果:

6. 浏览器缓存

6.1 协商缓存(Etag、Last-Modified)

6.1.1 协商缓存基本过程

1)第一次请求

  • 客户端发送 GET 请求,去请求文件;
  • 服务器处理请求,返回文件内容和一堆 Header,包括 Etag、Last-Modified,状态码 200

2)第二次请求

  • 客户端发送 GET 请求,去请求文件(注意:这个时候客户端请求头上,会带 上 if-none-match 值为 Etag 和 if-modified-since 值为 Last-Modified)
  • 服务器判断 Etag 和计算出来的 Etag 是否匹配,若返回状态为 304,则客户端继续使用本地缓存

6.1.2 Etag VS Last-Modified

当 ETag 和 Last-Modified 同时存在时,服务器优先检查 ETag

Etag 是服务器文件的唯一标识,当文件内容变化时,Etag 值也会发生变化

Etag 主要为了解决 Last-Modified 无法解决的一些问题。一些文件也许会周期性的更改,但是它的内容并不改变(也就是说,仅仅改变了修改时间),此时希望重用缓存,而不是重新请求

6.2 强制缓存(Expires、Cache-Control)

6.2.1 Cache-Control VS Expires

Cache-Control:max-age —— 表示缓存内容在 xxx 秒后失效;【优先级更高】

Expires —— 表示服务端返回的到期时间;也就是说,返回的是服务端时间,与客户端时间相比,可能会时间不一致

6.2.2 Cache-Control: no-cache VS Cache-Control: no-store

Cache-Control: no-cache —— 浏览器每次都会向服务器发起请求,来验证当前缓存的有效性

Cache-Control: no-store —— 响应不被缓存

7. 垃圾回收机制

7.1 GC 垃圾回收策略

7.1.1 标记清除

分为 标记 和 清除 两个阶段:

  • 标记阶段 —— 把所有活动对象做上标记
  • 清除阶段 —— 把没有标记(也就是非活动对象)销毁

基本步骤:

  • 在运行时,会给内存中的所有变量都加上一个标记,假设他们都是垃圾,全标记为 0
  • 然后从各个根对象开始遍历,把不是垃圾的节点改成 1
  • 清理所有标记为 0 的垃圾,销毁并回收它们所占用的内存空间
  • 最后,把所有内存中对象标记修改为 0,等待下一轮垃圾回收

7.1.2 引用计数

一个对象,如果没有其他对象引用到它,这个对象就是 零引用,将被垃圾回收机制回收

它的策略是 —— 跟踪记录每个变量值被使用的次数

基本步骤: 

  • 一个对象被其他对象引用时,这个对象的引用次数就为 1,如果同一个值又被赋给另一个变量,那么引用数加 1,如果该变量的值被其他的值覆盖了,则引用次数减 1
  • 当这个值的引用次数变为 0 的时候,说明没有变量在使用,这个值没法被访问了,回收空间,垃圾回收器会在运行的时候,清理掉引用次数为 0 的值占用的内存

7.2 分代式垃圾回收机制

V8 采用了一种代回收的策略,将内存分为两个生代:

  • 新生代 中的对象,为存活时间较短的对象
  • 老生代 中的对象,为存活时间较长 或 常驻内存的对象

基本步骤:

  • 新老生代,采用不同的垃圾回收算法,来提高效率
  • 对象最开始都会先被分配到新生代(如果新生代内存空间不够,直接分配到老生代)
  • 新生代中的对象会在满足某些条件后,被移动到老生代,这个过程也叫晋升

 

7.2.1 新生代的垃圾回收方式

将内存空间一分为二,分为:

  • From 空间(使用状态)
  • To 空间(闲置状态)

当新生代内存不足时,会将 From 空间中存活的对象,复制到到 To 空间,然后将 From 空间清空,交换 From 空间和 To 空间(将原来的 From 空间变为 To 空间),继续下一轮

7.2.2 老生代的垃圾回收方式

V8在老生代中,主要采用了 Mark-Sweep 和 Mark-Compact 相结合的方式

Mark-Sweep 遍历堆内存中的所有对象,并标记活着的对象,在随后的清除阶段,只清除没有被标记的对象,这就导致了 —— 在进行清除回收以后,内存碎片化

Mark-Compact 用来解决内存碎片的问题,将将存活对象向内存一侧移动,清空内存的另一侧,这样空闲的内存都是连续的

7.2.3 新老生代在不同系统的内存大小

64 位系统,新生代内存大小为 32MB,老生代内存为 1.4G

32 位系统,新生代内存大小为 16MB,老生代内存为 0.7G

7.3 垃圾回收机制参考文章

「硬核JS」你真的了解垃圾回收机制吗 - 掘金JavaScript 是门魅力无限的语言,关于它的 GC(垃圾回收)方面,你了解多少呢?想来大部分人是因为面试才去看一些面试题从而了解的GC,当然,我们可不仅仅是为了面试,目的是一次性彻底搞懂GC!https://juejin.cn/post/6981588276356317214

V8 内存浅析 - 知乎这篇文章包括以下内容,阅读完大概需要 6 分钟。 简介V8 内存构成V8 垃圾生命周期(垃圾回收)使用 Chrome 调优前端代码使用 alinode 调优 node.js 进程 简介 V8 是谷歌开发的高性能 JavaScript 引擎,该引擎使用 …https://zhuanlan.zhihu.com/p/33816534

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
浏览器是重要的互联网入口,一旦受到漏洞攻击,将直接影响到用户的信息安全。作为攻击者有哪些攻击思路,作为用户有哪些应对手段?在本书中我们将给出解答,带你了解浏览器安全的方方面面。本书兼顾攻击者、研究者和使用者三个场景,对大部分攻击都提供了分析思路和防御方案。本书从攻击者常用技巧的“表象”深入介绍浏览器的具体实现方式,让你在知其然的情况下也知其所以然。 第1篇 初探浏览器安全 1 1 漏洞与浏览器安全 3 1.1 漏洞的三要素 3 1.2 漏洞的生命周期 4 1.3 浏览器安全概述 5 1.4 浏览器安全的现状 7 1.5 浏览器的应对策略 9 1.6 “白帽子”与浏览器厂商的联手协作 9 1.7 全书概览 10 1.8 本章小结 12 2 浏览器中常见的安全概念 13 2.1 URL 13 2.1.1 URL的标准形式 15 2.1.2 IRI 16 2.1.3 URL的“可视化”问题——字形欺骗钓鱼攻击 18 2.1.4 国际化域名字形欺骗攻击 19 2.1.5 自纠错与Unicode字符分解映射 20 2.1.6 登录信息钓鱼攻击 23 2.2 HTTP协议 24 2.2.1 HTTP HEADER 25 2.2.2 发起HTTP请求 26 2.2.3 Cookie 28 2.2.4 收到响应 29 2.2.5 HTTP协议自身的安全问题 31 2.2.6 注入响应头:CRLF攻击 31 2.2.7 攻击响应:HTTP 401 钓鱼 32 2.3 浏览器信息安全的保障 33 2.3.1 源 33 2.3.2 同源准则 34 2.3.3 源的特殊处理 34 2.3.4 攻击同源准则:IE11跨任意域脚本注入一例 35 2.4 特殊区域的安全限制 37 2.4.1 安全域 37 2.4.2 本地域 37 2.5 伪协议 38 2.5.1 data伪协议 38 2.5.2 about伪协议 40 2.5.3 javascript/vbscript伪协议 41 2.5.4 伪协议逻辑出错:某浏览器跨任意域脚本注入一例 42 2.6 本章小结 43 3 探索浏览器的导航过程 45 3.1 导航开始 45 3.1.1 浏览器的导航过程 46 3.1.2 DNS请求 46 3.1.3 DNS劫持和DNS污染 47 3.1.4 导航尚未开始时的状态同步问题 48 3.1.5 实例:针对导航过程发起攻击 49 3.2 建立安全连接 50 3.2.1 HTTPS 50 3.2.2 HTTPS请求中的Cookie 51 3.3 响应数据的安全检查——XSS过滤器 52 3.3.1 IE XSS Filter的实现原理 53 3.3.2 Chrome XSSAuditor的工作原理 55 3.4 文档的预处理 56 3.4.1 浏览器对HTML文档的标准化 56 3.4.2 设置兼容模式 57 3.5 处理脚本 59 3.5.1 脚本的编码 60 3.5.2 IE的CSS expression的各种编码模式 62 3.5.3 浏览器的应对策略:CSP 63 3.5.4 “绕过”CSP:MIME Sniff 65 3.5.5 简单的Fuzz:混淆CSS expression表达式 68 3.6 攻击HTML标准化过程绕过IE/Chrome的XSS Filter 71 3.7 本章小结 73 4 页面显示时的安全问题 75 4.1 点击劫持 76 4.1.1 点击劫持页面的构造 76 4.1.2 X-Frame-Options 78 4.2 HTML5的安全问题 80 4.2.1 存储API 81 4.2.2 跨域资源共享 83 4.2.3 基于FullScreen和Notification API的新型钓鱼攻击 84 4.2.4 组合API后可能导致的安全问题 87 4.2.5 引入新的XSS 攻击向量 87 4.2.6 互联网威胁 89 4.3 HTTPS与中间人攻击 92 4.3.1 HTTPS的绿锁 92 4.3.2 HTTPS有多安全? 94 4.3.3 HSTS 96 4.3.4 使用SSLStrip阻止HTTP升级HTTPS 97 4.3.5 使用Fiddler对PC端快速进行中间人攻击测试 99 4.3.6 使用Fiddler脚本和AutoResponse自动发起中间人攻击 101 4.4 本章小结 103 5 浏览器扩展与插件的安全问题 105 5.1 插件 106 5.1.1 ActiveX 106 5.1.2 ActiveX的安全问题 107 5.1.3 ActiveX的逻辑漏洞 108 5.1.4 NPAPI、PPAPI 111 5.2 定制浏览器的扩展和插件的漏洞 113 5.2.1 特权API暴露 114 5.2.2 DOM 修改引入攻击向量 114 5.2.3 Windows文件名相关的多个问题 115 5.2.4 NPAPI DLL的问题 116 5.2.5 同源检查不完善 117 5.2.6 Content Script劫持 118 5.2.7 权限隔离失败 118 5.2.8 配合切核策略+本地内部页XSS执行代码 118 5.2.9 下载服务器限制宽松 119 5.2.10 TLDs判定问题 119 5.2.11 经典漏洞 120 5.2.12 中间人 120 5.3 Adobe Flash插件与Action Script 121 5.3.1 Flash的语言——Action Script 121 5.3.2 Flash文档的反编译、再编译与调试 122 5.3.3 SWF的网络交互:URLLoader 124 5.3.4 crossdomain.xml与Flash的“沙盒” 125 5.3.5 ExternalInterface 126 5.3.6 FLASH XSS 126 5.3.7 Microsoft Edge中的Flash ActiveX 130 5.4 浏览器的沙盒 131 5.4.1 受限令牌 132 5.4.2 完整性级别与IE的保护模式 133 5.4.3 任务对象 134 5.5 本章小结 135 6 移动端的浏览器安全 137 6.1 移动浏览器的安全状况 138 6.2 移动端的威胁 141 6.2.1 通用跨站脚本攻击 141 6.2.2 地址栏伪造 142 6.2.3 界面伪装 143 6.3 结合系统特性进行攻击 144 6.3.1 Android一例漏洞:使用Intent URL Scheme绕过Chrome SOP 144 6.3.2 iOS的一例漏洞:自动拨号泄露隐私 146 6.3.3 Windows Phone一例未修补漏洞:利用Cortana显示IE中已保存密码 147 6.4 本章小结 149 第2篇 实战网马与代码调试 151 7 实战浏览器恶意网页分析 153 7.1 恶意网站中“看得见的”攻防 153 7.2 恶意脚本的抓取和分析 155 7.2.1 发现含攻击代码的网址 156 7.2.2 使用rDNS扩大搜索结果 156 7.2.3 下载攻击代码 157 7.2.4 搭建测试环境 158 7.2.5 初识网马反混淆工具 158 7.2.6 恶意脚本中常见的编码方式 159 7.3 一个简单的挂马代码的处理 169 7.3.1 快速判断挂马 169 7.3.2 JS代码的格式化 170 7.4 更为复杂的代码处理:对Angler网马工具包的反混淆 170 7.4.1 Angler EK的特征 170 7.4.2 推理:找出代码中的“解密-执行”模式 172 7.4.3 检证:确定“解密-执行”模式的位置和方法 175 7.4.4 追踪:使用浏览器特性判断用户环境 179 7.4.5 利用漏洞CVE-2014-6332发起攻击 188 7.5 本章小结 190 8 调试工具与Shellcode 191 8.1 调试工具的用法 191 8.1.1 调试符号 191 8.1.2 WinDbg的用法 192 8.1.3 IDA的用法 195 8.1.4 OllyDbg的用法 199 8.2 与Shellcode的相关名词 201 8.2.1 机器指令 201 8.2.2 控制关键内存地址 203 8.2.3 NOP Slide 204 8.2.4 Magic Number 0x8123 205 8.3 Shellcode的处理 205 8.3.1 实现通用的Shellcode 206 8.3.2 调试网马中的Shellcode 212 8.4 本章小结 218 第3篇 深度探索浏览器漏洞 219 9 漏洞的挖掘 221 9.1 挖0day 221 9.1.1 ActiveX Fuzzer 的原理 221 9.1.2 使用AxMan Fuzzer来Fuzz ActiveX插件 222 9.1.3 现场复现 225 9.2 DOM Fuzzer的搭建 229 9.2.1 搭建运行Grinder的环境 230 9.2.2 Fuzzer的结构与修改 231 9.2.3 现场复现 232 9.3 崩溃分析 233 9.3.1 哪些典型崩溃不能称作浏览器漏洞 233 9.3.2 ActiveX崩溃一例 236 9.3.3 IE11崩溃一例 238 9.4 本章小结 244 10 网页的渲染 245 10.1 网页的渲染 245 10.1.1 渲染引擎 245 10.1.2 DOM结构模型 247 10.1.3 IE解析HTML的过程 249 10.1.4 IE的Tokenize 251 10.1.5 Chrome解析HTML的过程 253 10.1.6 Chrome的Tokenize 254 10.2 元素的创建 256 10.2.1 IE中元素的创建过程 256 10.2.2 Chrome中元素的创建过程 257 10.2.3 元素的生成规律 258 10.3 实战:使用WinDbg跟踪元素的生成 260 10.4 实战:使用WinDbg跟踪元素的插入 263 10.5 实战:使用WinDbg跟踪元素的释放 264 10.6 本章小结 266 11 漏洞的分析 267 11.1 分析IE漏洞CVE-2012-4969 267 11.1.1 崩溃分析 268 11.1.2 追根溯源 270 11.2 分析JScript9漏洞CVE-2015-2425 271 11.2.1 跟踪漏洞 275 11.3 Hacking Team的Flash漏洞CVE-2015-5119 分析 276 11.3.1 静态阅读:成因分析 276 11.3.2 Vector的覆盖过程 278 11.4 本章小结 279 12 漏洞的利用 281 12.1 ShellCode的编写 281 12.2 CVE-2012-4969 的利用 284 12.2.1 DEP/ASLR绕过 287 12.3 CVE-2015-5119的Vector 296 12.4 本章小结 301 附录 303 附录A IE(Edge)的URL截断 303 附录B IE的控制台截断 304 附录C 表单中的mailto: 外部协议 305 附录D 危险的regedit: 外部协议 306 附录E IE XSS Filter的漏洞也会帮助执行XSS 307 附录F 更高级的策略保护——CSP Level 2 308 附录G 更快的执行速度——JScript5 to Chakra 309 附录H Chakra的整数存储 310 附录I 安全实践 311 参考资料 315
Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌。Vue Router提供了两种模式:hash模式和history模式。 在hash模式下,路由的路径会被设置成URL的hash部分(即#号后面的部分),而在history模式下,路由的路径会被设置成URL的路径部分(即域名后面的部分)。 Vue Router的实现原理是通过监听URL的变化,然后根据不同的URL路径匹配到对应的组件进行渲染。在hash模式下,Vue Router通过监听window对象的hashchange件来实现URL的变化检测;在history模式下,Vue Router通过HTML5提供的History API来实现URL的变化检测。 具体来说,在history模式下,Vue Router使用了HTML5提供的History API中的pushState()和replaceState()方法来实现URL的变化。pushState()方法可以向浏览器的历史记录中添加一条新的记录,而replaceState()方法则可以替换当前的历史记录。通过这两个方法,Vue Router可以实现在不进行页面刷新的情况下,改变URL的路径,并且保证浏览器的前进和后退按钮可以正常使用。 下面是一个简单的示例代码,演示了如何使用Vue Router实现基本的路由功能: ```javascript import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ] const router = new VueRouter({ mode: 'history', routes }) new Vue({ router, render: h => h(App) }).$mount('#app') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值