浏览器渲染
从输入 URL 到页面呈现发生了什么
假设我们正在请求`[http://www.baidu.com](http://www.baidu.com)`这个网址1. 构建请求
浏览器会构建请求行
// 请求方法是GET 路径为/根路径 HTTP版本为 1.1
GET / HTTP / 1.1;
2. 检查强缓存
通过 Expires 和 Cache-Control 头部去检查强缓存
,如果命中则直接使用缓存,否则进入协商缓存
。
强缓存不需要发起 HTTP 请求,协商缓存需要。
协商缓存通过E-Tag + If-NO-Match
和Last-Modified + If-Modified-Since
两个组合从文件标志、修改时间两个方面去判断是否需要更新缓存,如果协商缓存命中,返回304 No Modified
,读取缓存。
缓存位置:
- Service Worker, 离线缓存
- Memory Cache, 内存缓存
- Disk Cache, 磁盘缓存
- Push Cache,推送缓存
3. DNS 解析
通过DNS域名解析系统(端口号53
)将 URL 映射到具体的 IP 地址。
在区域传输
(域名数据更新时执行同步)的时候使用TCP协议
,在域名解析的时候使用UDP协议
DNS 查询过程:浏览器缓存 -> 本地DNS服务器 -> 根域名服务器 -> 顶级域名服务器 -> 权威域名服务器 -> 缓存 -> 任一级命中则返回结果
DNS 解析后的 IP 会给浏览器缓存,下次访问时直接读取缓存,不需要再次解析。
4. 建立 TCP 连接
解析出 IP 地址后,根据地址和端口发起 TCP 请求。HTTP 默认端口号为80
,HTTPS 默认端口号为443
Chrome 下一个域名最多只有 6 个 TCP 连接,超过则需要等待(引申下,队头阻塞问题
)
TCP 是面向连接的、可靠的、基于字节流的传输层协议。
TCP 通过三次握手
建立客户端与服务器的连接、数据包校验
保证接收方收到完整数据、四次挥手
断开连接。
响应完成后,需要判断Connection
字段,如果请求头或响应头中包含Connection: Keep-Alive,表示建立了持久连接,这样TCP
连接会一直保持,之后请求统一站点的资源会复用这个连接。
否则断开 TCP 连接,请求-响应流程结束。
5. 渲染
客户端拿到 html 后解析并渲染出来:
- 构建 DOM 树:词法解析 DOM 树,由 DOM 元素及属性节点组成,根为 document
- 构建 CSS 规则树:解析 CSS,生成 CSS 规则树
- 构建 render 渲染树:浏览器将 DOM 树和 CSS 规则树结合,构建出渲染树
- 布局(Layout):计算节点在屏幕的位置
- 绘制:遍历 render 树,在 UI 后端层绘制每个节点
浏览器渲染优化
(1)JS 引入
- 尽量将 JavaScript 文件放在 body 的最后
- body 中间尽量不要写
<script>
标签 - 通过 async/defer 优化 script 标签引入:defer 标签,顺序执行,async 标签异步执行
(2)CSS 引入
根据使用情况分 3 种模式写入:
- link:异步加载资源,不会阻碍继续渲染
- @import:GUI 停止渲染,在资源加载完成前会阻碍浏览器渲染
- style: GUI 直接渲染, css 尽量放在 head 标签中会先加载,减少首次渲染时间
(3)减少回流重绘
进程与线程
一个标准的线程由线程 ID、当前指令指针(PC)、寄存器和堆栈组成。
而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成
产生死锁的原因:
- 竞争资源:竞争不可剥夺资源(一台打印机)/临时资源
- 进程间推进顺序非法, p1 持续占用 R1,P2 持续占有 R2,P1 调用 R2 就会出现问题
浏览器安全
XSS 跨站脚本攻击
XSS 全称是 Cross Site Scripting(跨站脚本),为了和 CSS 区分,所以叫 XSS
XSS 攻击指的是浏览器中执行恶意脚本,从而获取用户信息并进行操作:
- 窃取
Cookie
- 监听用户行为,比如用户输入账户密码后发送至黑客服务器
- 修改 DOM 伪装登录表单
- 在页面生成浮窗广告
XSS 实现方式
通常 XSS 攻击实现方式有三种:存储型,反射型,文档型。
存储型,将脚本存储到服务器数据库,然后在客户端执行。常见场景就是在留言评论区提交一段恶意脚本,若没有做转义工作就存储到了数据库,在页面渲染时直接执行
。
反射型,指将恶意脚本作为网络请求的一部分,没有存储到服务器数据库中。 比如下方请求,服务器拿到search
参数,将内容返回给浏览器端,浏览器发现是个脚本直接执行,这样就被攻击了。
https://baidu.com?search=<script>alert("你完蛋了")</script>
文档型,不会经过服务端,而是作为中间人的角色,在数据传输过程劫持到网络数据包,然后修改里面的 html 文档!劫持方式包括 WIFI路由器劫持
和本地恶意软件
等。
XSS 防范措施
- 对用户的输入进行转码或者过滤。
- 利用 CSP。浏览器的内容安全策略,核心思想是让服务器决定客户端加载哪些资源。具体可以完成:限制其他域的资源加载; 禁止向其他域提交数据;提供上报机制,帮助及时发现 XSS 攻击。
- 利用 HttpOnly。设置 Cookie 的
HttpOnly
属性后,JavaScript 无法读取 Cookie 的值。这样可以很好的防范 XSS 攻击。
CSRF 跨站请求伪造攻击
CSRF(Cross-Site Request Forgery, 跨站请求伪造),指黑客通过诱导用户点击链接,打开黑客的网站,利用用户当前登录状态发起跨站请求。
原理
进入黑客页面后,通过以下三种方式携带当前用户登录过的 cookie 信息,进行恶意操作。
- 自动发起 GET 请求
- 自动发起 POST 请求
- 诱导点击发送 GET 请求(一刀 999)
这就是 CSRF 的攻击原理,与XSS
攻击相比,CSRF 攻击不需要将代码注入用户当前页面,而是跳转到新页面,利用服务器验证漏洞和用户登录状态来模拟用户操作。
CSRF 防范措施
- 利用 Cookie 的 SamSite 属性
CSRF 攻击重要的一环就是发送目标站点的 cookie,利用这份 cookie 来模拟用户身份。
SamSite 可以设定三个值,Strict
、Lax
和None
Strict 模式下,浏览器完全禁止第三方请求携带 Cookie。如 baidu.com 网站只能在 baidu.com 域名中请求才能携带 Cookie,其他网站请求不能。
Lax 模式下,相对宽松些,只能在GET 方法提交表单或者a 标签发送 GET 请求时携带 Cookie,其他情况不能。
None 模式,请求默认会带上 Cookie。
- 验证来源站点 利用请求头的两个字段:Origin 和 Refer 其中Origin只包含域名信息,而Refer包含了具体的 URL 路径。 但这两个是可以伪造的,在 Ajax 请求中自定义请求头即可,安全性略差。
- CSRF Token
浏览器向服务器发起请求时,服务器生成的字符串 Token将其植入返回的页面中。
之后浏览器要发送请求,必须携带该字符串,然后服务器来验证合法性。通常第三方站点拿不到该 Token,请求会被服务器拒绝。