浏览器原理

浏览器安全

xss攻击

跨站脚本攻击,在网站注入恶意脚本,使之在用户的浏览器上运行,盗取用户信息。

没有对恶意代码进行过滤,与正常的代码混合在一起了。

可以进行的操作

  1. 获取页面数据
  2. 破坏页面结构
  3. 流量劫持
  4. dos攻击,发送合理请求,占用服务器资源

攻击类型

  1. 存储型,恶意脚本会存储在目标服务器上
  2. 反射型:
  3. DOM型:通过修改页面的dom结构形成xss
  • 攻击者构造出特殊的 URL,其中包含恶意代码。
  • ⽤户打开带有恶意代码的 URL。
  • ⽤户浏览器接收到响应后解析执⾏,前端 JavaScript 取出 URL 中的恶意代码并执⾏。
  • 恶意代码窃取⽤户数据并发送到攻击者的⽹站,或者冒充⽤户的⾏为,调⽤⽬标⽹站接⼝执⾏攻击者指定的操作

防御方法

  1. 使用csp,csp本质是建立一个白名单,告诉浏览器那些外部资源可以加载和执行,防止恶意代码的注入攻击
    1. 一种是设置 HTTP 首部中的 Content-Security-Policy,一种是设置 meta 标签的方式
  2. 浏览器的执行来防御,纯前端的方式,不用服务器端渲染
    1. 不用服务器端渲染

CSRF攻击

跨站请求伪造攻击,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

利用cookie会在同源请求中携带,发送给服务器的特点,来实现用户的冒充

  • POST 类型的 CSRF 攻击,比如构建一个表单,然后隐藏它,当用户进入页面时,自动提交这个表单。

如何防御csrf攻击

在设置 cookie 属性的时候设置 Samesite ,限制 cookie 不能作为被第三方使用


有那些可能引起前端安全的问题

  1. 跨站脚本(xss):一种代码注入方式
  2. iframe滥用:ifrmae由第三方提供,默认情况下不受控制
  3. 跨站请求伪造:
  4. 恶意第三方库

网络劫持有哪几种,怎么防范

dns劫持

        修改本地dns记录,引导用户流量到缓存服务器

http劫持

        运营商会修改你的http相应内容


浏览器进程及功能

  • 浏览器进程:主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
  • 渲染进程:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
  • GPU 进程: UI 界面都选择采用 GPU 来绘制
  • 网络进程:主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
  • 插件进程:主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。

渲染进程的线程

GUI渲染线程 负责渲染浏览器页面,解析HTML、CSS,构建DOM树、构建CSSOM树、构建渲染树和绘制页面;当界面需要重绘或由于某种操作引发回流时,该线程就会执行。

注意:GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。

(2)JS引擎线程 JS引擎线程也称为JS内核,负责处理Javascript脚本程序,解析Javascript脚本,运行代码;JS引擎线程一直等待着任务队列中任务的到来,然后加以处理,一个Tab页中无论什么时候都只有一个JS引擎线程在运行JS程序;

注意:GUI渲染线程与JS引擎线程的互斥关系,所以如果JS执行的时间过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞。

(3)时间触发线程 时间触发线程属于浏览器而不是JS引擎,用来控制事件循环;当JS引擎执行代码块如setTimeOut时(也可是来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件触发线程中;当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理;

注意:由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行);

(4)定时器触发进程 定时器触发进程即setInterval与setTimeout所在线程;浏览器定时计数器并不是由JS引擎计数的,因为JS引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确性;因此使用单独线程来计时并触发定时器,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行,所以定时器中的任务在设定的时间点不一定能够准时执行,定时器只是在指定时间点将任务添加到事件队列中;

注意:W3C在HTML标准中规定,定时器的定时时间不能小于4ms,如果是小于4ms,则默认为4ms。

(5)异步http请求线程

  • XMLHttpRequest连接后通过浏览器新开一个线程请求;
  • 检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将回调函数放入事件队列中,等待JS引擎空闲后执行;

  • 死锁产生的原因和解决思索
    • 定义:多个进程运行过程中因争夺资源而造成的一种僵局。
    • 原因
      • 互斥条件:资源互斥
      • 请求和保持条件:不放弃
      • 不剥夺:不能被抢
      • 环路等待:
    • 解决
      • 资源一次分配完成(请求保持)
      • 一个资源得不到分配,那么也不给他其他
      • 可剥夺
      • 资源有序分配法(按编号一次分配)

浏览器缓存

位置

  1. service worker:运行在浏览器背后的独立线程,完成离线缓存,消息推送,网络代理等功能。
  2. memory cache:包含已经抓取到的资源,关闭页面缓存释放
  3. disk cache

强缓存与协商缓存

使用强缓存(memory cache    disk cache)

        若资源有效则直接使用,不再发请求,返回状态码200。

        通过两种方式来设

                http头信息中的expires(过期时间,通过本地时间来判断)和

                cache-conrol(优先级更高,使用相对时间)属性

协商缓存

        命中协商缓存,会向服务器发送请求,若未修改则使用,返回状态码304。

        通过两种方式来设

                http头信息中的Etag(资源文件的标识)

                   last-modified(服务器,资源最后被修改的时间)/ if-modified-since(,携带上次last,是否过期)

                   Etag/if-None-Match:与服务器资源是否一致(一致304,不一致200)

1. 当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。

2. 当f5刷新网页时,跳过强缓存,但是会检查协商缓存。

3. 浏览器地址栏中写入URL,回车 浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。(最快)


浏览器渲染原理

  1. 解析收到文档,生成dom树
  2. 解析css,生成cssom树
  3. 根据dom树和cssom规则树构建render树。
  4. 根据渲染树进行布局,弄清楚各个节点在渲染页面的位置和大小(回流)
  5. 绘制阶段,遍历渲染树,调用paint方法,将他们的内容绘制在屏幕上

浏览器渲染优化

  1. js
    1. 将js文件放在body最后
    2. 中间不要放script
    3. script的引入方式
      1. script
        1. 立即停止页面渲染,去加载js,加载完成后立即执行
      2. async
        1. 下载完成后,立即异步加载,加载后立即执行,多个async属性不能保证加载顺序
      3. defer
        1. 下在完成后,立即异步加载,加载后等dom解析好再执行。多个defer按顺序执行
  2. css
    1. 使用css样式
      1. link
        1. 派发一个新线程去加载,与此同时gui线程会继续向下渲染代码
      2. import
        1. gui暂停渲染,加载资源
      3. style
        1. 直接渲染
  3. 减少回流与重绘
    1. 不用table布局
    2. 使用css表达式
    3. 不要频繁操作元素样式
    4. 比卖你频繁操作dom,创建文档片段,在其上进行所有dom操作,最后一次性加入文档中
    5. 将dom的多个读操作放一款,得益于浏览器的渲染队列机制

文档的预解析

执行js时,另外一个线程解析剩下的文档,并加载后面需要通过网络加载的资源,这种方式可以使资源并行加载,从而使整体速度更快。只解析外部资源的引用


css如何阻塞文档解析(js中请求css)

js脚本执行时可能有请求样式的信息,此时会延迟js脚本的执行,直至完成cssom的下载构建


优化关键渲染路径的步骤

对关键路径进行分析和特性描述

最大限度减少关键资源的数量

优化关键字节数以缩短下载时间


浏览器本地存储

  1. cookie
    1. 大小4kb,
    2. 每次http请求都会携带
    3. 无法跨域名
      1. Name:cookie的名称
      2. Value:cookie的值,对于认证cookie,value值包括web服务器所提供的访问令牌;
      3. Size: cookie的大小
      4. Domain:可以访问该cookie的域名,Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围。
      5. HTTP: 该字段包含HTTPOnly 属性 ,该属性用来设置cookie能否通过脚本来访问,默认为空,即可以通过脚本访问。在客户端是不能通过js代码去设置一个httpOnly类型的cookie的,这种类型的cookie只能通过服务端来设置。该属性用于防止客户端脚本通过document.cookie属性访问Cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HTTPOnly的应用仍存在局限性,一些浏览器可以阻止客户端脚本对Cookie的读操作,但允许写操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头。
      6. Expires/Max-size : 此cookie的超时时间。若设置其值为一个时间,那么当到达此时间后,此cookie失效。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。
  2. localStorage
    1. 5mb
    2. 持久存储,
    3. 金在本地,不随http携带
    4. 兼容性问题
  3. sessionStorage
    1. 窗口关闭就删除
    2. 金在本地
  4. indexDB
  5. IndexedDB有哪些特点?

    IndexedDB 具有以下特点:

  6. 键值对储存:IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
  7. 异步IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
  8. 支持事务:IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
  9. 同源限制: IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  10. 储存空间大:IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
  11. 支持二进制储存:IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

同源策略

是浏览器最核心也最基本的安全功能。

不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。

协议、端口号、域名必须相同

解决方法

  1. jsonp
    1. 简介:利用script标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的json数据,jsonp一定要有对方服务器支持
    2. 优点:jsonp兼容性好
    3. 缺点:
      1. 支持get方法,局限性
      2. 容易遭受xss攻击
    4. 实现流程
      1. 声明一个回调函数(show),函数名做参数值,要传递给跨域请求数据的服务器,函数形参要获取目标数据(服务器返回的data)
      2. 创建一个script标签,把那个跨域的api数据接口地址赋值给script的src,还要在这个地址中向服务器传递该函数名(通过?传参)
      3. 服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和他需要给你的数据拼接成一个字符串,例如:传递进去的函数名是show,他准备好的数据是show(‘ 我不爱你 ’)
      4. 最后服务器把准备的数据通过http协议返回给客户端,客户端再调用执行之前声明的回调函数show,对返回的数据进行操作。
      5. // index.html
        function jsonp({ url, params, callback }) {
          return new Promise((resolve, reject) => {
            let script = document.createElement('script')
            window[callback] = function(data) {
              resolve(data)
              document.body.removeChild(script)
            }
            params = { ...params, callback } // wd=b&callback=show
            let arrs = []
            for (let key in params) {
              arrs.push(`${key}=${params[key]}`)
            }
            script.src = `${url}?${arrs.join('&')}`
            document.body.appendChild(script)
          })
        }
        jsonp({
          url: 'http://localhost:3000/say',
          params: { wd: 'Iloveyou' },
          callback: 'show'
        }).then(data => {
          console.log(data)
        })
        

  2. cors(跨域资源共享)
    1. 需要浏览器和后端同时支持
    2. 分为简单请求和非简单请求
      1. 简单请求
        1. 满足以下条件
          1. 使用下列方法
            1. head
            2. get
            3. post
          2. Content-Type的值仅限于下列三者之一
            1. text/plain
            2. multipart/from-data
            3. application/x-www-form-urlencoded
      2. 复杂请求
        1. 在正式通信前会增加一次查询请求,option方法,来知道服务端是否允许跨域请求
        2. 实际操作
  3. postMessage
    1. 是H5中的api,允许
      1. 多窗口之间传递消息
      2. 页面与嵌套的iframe消息传递
      3. 页面和其打开的窗口信息传递
  4. webSocket
    1. 实现了浏览器和服务器的全双工通信
  5. node中间代理
    1. 实现原理:同源策略是浏览器要遵守的标准,服务器向服务器请求则可以跳过
    2. 接收客户端请求
    3. 转发给服务器
    4. 服务器相应数据
    5. 将响应转发给客户端
  1. nginx反向代理
    1. 类似node中间代理,搭建中间服务器,转发请求

正向代理和反向代理的区别

两者都是client-proxy-server的结构,区别在于正向代理proxy是client设置的,用来隐藏client

反向代理中,proxy是server设置,用来隐藏server 


事件委托

利用事件冒泡机制,因为事件再冒泡过程中会上传到父节点,父节点可以通过对象获取到目标节点,因此可以把子节点监听函数定义在父结点上,由父节点监听函数统一处理多个子元素的事件

特点

  1. 减少内存消耗
  2. 动态绑定事件 

局限

事件委托会影响页面性能


同步和异步

同步,当一个进程再遇见需要等待的请求时,一直等下去

异步,先执行其他,当消息返回时再执行


如何实现浏览器内多个标签页之间的通信?

实现多个标签页之间的通信,本质上都是通过中介者模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者,让标签页和中介者进行通信,然后让这个中介者来进行消息的转发。通信方法如下:

  • 使用 websocket 协议,因为 websocket 协议可以实现服务器推送,所以服务器就可以用来当做这个中介者。标签页通过向服务器发送数据,然后由服务器向其他标签页推送转发。
  • 使用 ShareWorker 的方式,shareWorker 会在页面存在的生命周期内创建一个唯一的线程,并且开启多个页面也只会使用同一个线程。这个时候共享线程就可以充当中介者的角色。标签页间通过共享一个线程,然后通过这个共享的线程来实现数据的交换。
  • 使用 localStorage 的方式,我们可以在一个标签页对 localStorage 的变化事件进行监听,然后当另一个标签页修改数据的时候,我们就可以通过这个监听事件来获取到数据。这个时候 localStorage 对象就是充当的中介者的角色。
  • 使用 postMessage 方法,如果我们能够获得对应标签页的引用,就可以使用postMessage 方法,进行通信

进程与线程

  • 进程与进程之间完全隔离,一个进程崩溃不会影响其他进程
  • 进程与进程之间需要传递某些数据的话,就需要通过进程通信管道IPC来传递
  • 当一个进程关闭之后,操作系统会回收该进程的内存空间

  • 一个进程中的任意一个线程执行出错,会导致这个进程崩溃
  • 同一进程下的线程之间可以直接通信和共享数据
  • 一个进程中可以并发多个线程,每个线程并行执行不同的任务

进程通讯(两管,两信,小工,s)

匿名管道

  • 半双工,数据只能单向流动,要是想双向流动,必须创建两个管道;
  • 匿名管道只适用于具有父子关系的进程间

命名管道

        实现了不存在父子进程间的通信

消息队列

        通信不及时

        涉及到用户态和内核态之间的数据拷贝开销        ​​​​​​​

 共享内存

        共享内存可以使得多个进程可以直接读写在同一块内存空间中,这是效率最高的进程间通信方式。        

信号量

信号

Socket

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值