浏览器相关知识点

274 阅读11分钟

浏览器输入url后的详细过程:

  1. DNS解析(根据域名查询ip)
    DNS根据域名查询IP地址的过程为:浏览器缓存 --> 操作系统缓存 --> 路由器缓存 -–> 本地DNS缓存 --> 根DNS -–>顶级DNS -–> 权威DNS。

  2. TCP连接(三次握手)
    根据域名拿到IP地址,浏览器以一个随机端口-->服务器的WEB程序(nginx等)80端口发起TCP的连接请求-->服务器端-->网卡-->内核的TCP/IP协议栈(用于识别该连接请求,解封包),还可能经过网络防火墙(属于内核的模块)的过滤-->WEB程序-->建立TCP/IP连接。

  3. 发送http请求
    请求报文由请求行、请求头部、空行和请求数据 4 部分组成。

  4. 服务器处理请求
    一个响应由状态行、响应头部、空行和响应数据 4 部分组成。

  5. 释放tcp连接
    tcp udp 差别

  6. 浏览器解析HTML
    <!DOCTYPE html>指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令,这样浏览器才能获知文档类型

  7. 浏览器渲染页面
    DOM树、CSSOM树、render树、布局(位置、显隐)、图层(z-index)、图块化
    单线程(阻塞问题)
    reflow(回流)和repain(重绘)
    JS解析引擎完成的,比如谷歌的是V8
    同步、异步任务
    事件循环

  • reflow(回流)和repain(重绘)
    回流必将引起重绘,而重绘不一定会引起回流。
ex:只有颜色改变的时候就只会发生重绘而不会引起回流  

当页面布局和几何属性改变时就需要回流

ex:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变

filter opacity transformz transform3d属性3D转换不会触发回流(3D会创建独立图层,GPU可直接执行:CSS硬件加速)

  • 同步和异步: 线程,都有同步队列和异步队列 立即执行的任务队列,同步任务,比如一个简单的函数; 请求接口发送ajax,发送promise,或时间计时器等等,异步任务

  • 事件循环中,每进行一次循环操作称为tick(异步任务:先微任务,后宏任务) 宏观任务主要包含:setTimeoutsetInterval、script(整体代码)、I/O、UI 交互事件 微观任务主要包括:Promiseprocess.nextTick(Node.js环境)

  • 浏览器的进程、线程

  1. Browser进程
    浏览器的主进程,UI线程、Network线程、Storage线程
    输入url后首先由此进程进行响应,请求服务器
  2. Renderer进程(多线程)
    主要用于页面渲染,脚本执行,事件处理等(前端性能优化)
  3. Plugin进程
    使用该插件时才创建,如flash
  4. GPU进程
    3D 绘制等
    Renderer进程
    1. GUI渲染线程
      当界面需要重绘(repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
      GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
    2. JS引擎线程
      GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
    3. 事件触发线程
      控制事件循环
    4. 定时触发器线程
    5. 异步http请求线程

WebKit、Blink浏览器引擎

WebCore(渲染引擎html/dom/css/svg)、JSCore(苹果JS引擎)、V8引擎(谷歌JS引擎)
  • V8引擎(JS引擎) 源代码 -> 解析器 -> 抽象语法树(AST) -> JIT编译器 -> 本地可执行代码
  • 内联缓存 维护最近的方法调用中作为参数传递的对象类型的缓存,来预测将来作为参数传递的对象的类型,假设很准的话,效率就高
  • 内存分配(内存堆JS Heap) 年轻代 使用中(From空间) 空闲(To空间)、年老代、大对象
  • 垃圾回收 V8限制了JS能调用的内存(垃圾回收时阻塞JS线程)
    判断回收内容(是不是垃圾,该不该收)
    采用分代回收策略(新生代和老生代)
    新生代:遍历from,存活放入to;遍历完清空from;对调from和to的角色
    老生代:遍历所有对象,标记存活对象;遍历完清除未标记的(标记清除、标记整理)

http状态码

  • 100 客户端继续请求
    http1.1里post先发送header,获得100则继续发送body,获得401要求客户端进行HTTP需要认证,所以不用继续了,节省了带宽。
    http1.1还支持获得服务端对象的部分资源,是通过http请求头里的range头域实现的,返回206则代表了获取部分get请求。
  • 200 请求成功
  • 201 请求成功并在服务器端创建了新资源。
  • 202 请求被接受了,但是请求没有处理结束。
  • 206 代表实现了部分get请求。
  • 300 代表请求的资源有多种类型。
  • 301 代表请求的资源被永远移到了其他地方,reponse body里的location URL里指明了资源现在的位置。
  • 302 重定向,临时转移到其他地方。
  • 304 表示get请求不可用。
  • 400 请求有语法错误。
  • 401 认证失败
  • 403 请求被接收了,但是被拒绝服务。
  • 404 请求的url错误,请求的资源不存在。
  • 405 表示请求的方法不允许执行。
  • 407 表示客户端需要认证。
  • 414 表示请求的URL过长。
  • 500 服务器内部有错误。
  • 502 网关错误
  • 503 服务器暂时不提供http服务。
  • 504 网关超时

跨域:浏览器采用同源的安全策略

跨域访问:A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的

  • jsonp
    在html页面中通过相应的标签从不同域名下加载静态资源文件是被浏览器允许的(从js中调用不行)
    script=document.createElement(‘script’)
    getData(){}
    script.src = ‘http://uri:port?callback=getData’
    document.body.appendChild(‘script’)
    $.ajax({ type: ‘get’, url: ‘url’, data: {},datatype:’jsonp’})
    
  • 跨域资源共享CORS(W3C标准):(简单请求 & 非简单请求)
    允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
  • nginx代理跨域:
    将前端的服务请求(域名A)通过代理服务器(域名A,端口不同)做跳板机,反向代理访问(域名B)
  • vue中的跨域(vue.config.js):
        devServer: { proxy: { '/api': {
            target: 'http://10.113.88.194:8000'// 目标代理服务器地址
            changeOrigin: true, // 允许跨域
        }}}
    
    npm run serve启动node服务,配置vue-clidevServerproxy,浏览器将http请求先发到node本地服务,再由devServer转发到需要跨域的服务端

cookie后端获取不到的原因;如何保证获取

axios.defaults.withCredentials = true;//允许跨域携带cookie信息
$.ajax({ type: "GET", url: url,
      xhrFields: {
         withCredentials: true // 允许跨域携带cookie信息
      },
});
axios.interceptors.request.use(config => {
    config.headers['Authorization'] = 'Bearer '+token;
});

设置Auth后http先发出预检请求,即OPTIONS访问服务器是否允许跨域

ngnix location / { proxy_cookie_domain domino_server nginx_server; }

后端

res.header('Access-Control-Allow-Origin', 'http://localhost:8070'); // 允许访问的域名
res.header('Access-Control-Allow-Credentials', true); // 允许服务器端发送Cookie数据
res.header('Access-Control-Allow-Headers','Content-Type,Content-Length, Authorization);
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if (req.method == 'OPTIONS') {
  res.send(200); // 预检请求。
} else { next(); }

权限控制

基于角色的权限控制rbca(role based access control)
编辑角色 权限编辑 权限查询 路由赋值

this.$router.push({name:'monitoringDetail', query: {id: id}});
this.$router.push({ name: 'home', params: { userId: wise }})
this.$router.replace('position');
this.$router.go(-1);
const {href} = this.$router.resolve({ name: 'srvbotReqDetail', query})
window.open(href, '_blank');

请求数据,响应强行代理故意篡改,如何预防

CSRF攻击(跨站请求伪造)

  • 简单版:
    目标网站A:关注我 接口url?id=1 攻击网站B:页面嵌入<img style=”width:0” src=”url?id=1”>,打开就会自动关注我
  • 升级版:
    目标网站A:关注我 接口url?id=1,限制只获取POST请求数据
    攻击网站B:加多一层iframe,页面不会再重定向,增加攻击的隐蔽性。因为有跨域的问题,H1页面不使用XMLHTTPRequest发送POST请求;而form可以跨域post数据
    H1.html
         <body>
              <iframe style="display:none;" src="test2.html"></iframe>
         </body>
    
    H2.html
    <body>
         <form  name="formAttact" action="url" method="post">
              <input type="hidden" name="id" value="1"/>
              <input type="submit" value>
         </form>
         <script>
              document.forms.formAttact.submit();
         </script>
    </body>
    
  • 进阶版:
    目标网站A:关注我 接口url?id=1,限制只获取POST请求数据
    攻击网站B:某段文本是直接贴进HTML(未过滤),则将遭受XSS攻击。若直接把上面代码嵌入文本内容,打开B,自动关注我,这组合攻击方式称为XSRF

防御:

  1. 尽量使用POST,限制GET

  2. 浏览器Cookie策略(SameSite: Strict/Lax/None

  3. 验证 HTTP Referer 字段,记录了请求的来源地址, 可只允许处理Referer为当前域的求

  4. 加验证码

  5. Anti CSRF Token

    1. 用户访问某个表单页面。
    2. 服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
    3. 在页面表单附带上Token参数。
    4. 用户提交请求后, 服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。

    由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。

XSS攻击(跨站脚本攻击)(前端v-html、后端sql注入)

跨站脚本攻击 向web页面注入恶意代码
恶意代码被浏览器成功执行

防御

Cookie HttpOnly 禁止JS脚本操作Cookie
对“<”,“>”,“;”,“””等字符做过滤
任何内容输出到页面之前都必须加以en-code,避免不小心把htmltag显示出来。
vue-xss.js(xss.jsvue-xss(v-html=”$xss(content)”)

ajax、axios

// 跨域
axios.defaults.withCredentials = true;
// 拦截请求发送
axios.interceptors.request.use( config => {}, (error)=>{})
// 拦截请求响应
axios.interceptors.response.use( response => {}, (error)=>{})

axios导出的是Axios类中request方法

func(){let axios=new Axios(); let req=axios.request.bind(axios); return req;}
    [get, post].forEach(met =>{
        Axios.prototype.met=function(arg, ...args){
        return this.request({method: met, url: arg,  data: args})
    }
}
  • xhr XMLHTTPRequest对象(请求后端数据的方法)
  • ajax 封装原生XHR,除此以外还增添了对JSONP的支持
  • axios 封装原生XHR,Promise回调
  • fetch是基于promise设计的。但fetch没有使用XMLHttpRequest对象,没有封装ajax,而是原生js

登录方案 cookie token

单点登录方案
以Cookie作为凭证媒介
通过JSONP实现
通过页面重定向的方式
使用独立登录系统

cookie/session/token

  1. cookie属性\ cookie跨域共享 expires、path、domain、secure

    • cookie存放在浏览器,session存在服务器(在浏览器的cookie中存sessionId)
    • cookie大小不能超4K,浏览器限制一个站点最多保存20条cookie
    • cookie key:value (值是字符串) session id:obj (值是对象)
  2. token

    • 生成:token 的组成为:user.{user}.{HS256(user, secret)}。secret 是会话密钥,保存在服务端,不能泄漏。HS256 是加密算法,使用 RS256、HS512 也可以。
    • 验证:将请求中携带的 token 按照 . 分开,得到payload和sig。用secret对payload进行加密,将加密结果和sig比较,如果相同,那么通过验证。
  3. 数据存储 Cookie sessionStorage localStorage Vuex

    • cookie在http请求时自动携带,根据设定时间判断失效,同源窗口中共享
    • sessionStorage标签页关闭时失效,不共享
    • localStorage不清除永久有效,同源窗口中共享
    • localStorage、 sessionStorage
      storage中存储的是json数据,需要JSON.stringify()/JSON.parse()
      localStorage.setItem('role', res.role)  
      localStorage.clear()
      
    • Cookie
      import Cookie from 'js-cookie';  
      Cookie.set(TOKEN_KEY, token);  
      Cookie.remove(TOKEN_KEY);  
      

HTTP1.0、HTTP1.1 和 HTTP2.0 的区别

  • 缓存处理
    1.0 If-Modified-Since,Expires 1.1 Entity tag, If-Match

  • 错误通知管理
    1.1新增了24个错误响应状态码

  • Host头处理
    1.0中认为每台服务器都绑定一个唯一的IP地址,请求消息中的URL不传递主机名(hostname);现在一台物理服务器上可以存在多个虚拟主机,共享一个IP地址

  • 长连接
    1.1中默认开启Connection: keep-alive

  • 2.0
    1.X解析基于文本协议,2.0基于二进制格式
    多路复用(如websocket)(1.0每次都要新建连接; 1.1请求排队,单线程串行; 2.0请求可在同个连接上并行) header压缩
    服务端推送

http和https

  1. https协议需要到ca申请证书,需要费用。
  2. http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
    如何保证安全
    浏览器https://uri:port访问服务器,请求建立ssl连接 server收到请求,将证书(公匙)发给client 浏览器生成随机值,组装成会话密匙,利用公匙加密会话密匙,发送到server server利用私匙解出会话密匙,利用会话密匙加密通信next

http缓存(浏览器将http请求获取到的资源存储在本地的一种行为)

memory cache 内存缓存
disk cache 硬盘缓存
强制缓存:根据 header 中 ExpiredCache-Control 判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求
协商缓存:强缓存没有命中,浏览器发送请求到服务器,服务器根据 header 中的 Last-ModifiedETag 判断是否命中缓存,如果命中,则返回304,告诉浏览器资源未更新,可使用本地的缓存

CDN 缓存 回源

socket/websocket

Socket套接字,对TCP/IP协议的编程封装(类似http,但http是成文的互联网通信协议)
WebSocket 全双工通信,H5标准的一部分,同http一样是应用层协议,继承socket端到端连接的概念

get / post

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST么有。
GET参数通过URL传递,POST放在Request body中。

GET/POST都是TCP链接
GET和POST是HTTP协议中的两种发送请求的方法;
HTTP是基于TCP/IP通信协议。

UDP/TCP

无连接 面向连接 不可靠传输,无流量、阻塞控制 可靠传输,流量、阻塞控制 传输方式面向报文 面向字节流 首部开销小(8字节) 最小20byte,最大60byte 适用IP电话、视频会议、直播 适用要求可靠传输的应用,如文件传输 进程和线程

  1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
  2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线
  3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
  4. 调度和切换:线程上下文切换比进程上下文切换要快得多

encodeURI/encodeURIComponent

  • encodeURI(URIstring):
    对在 URI 中具有特殊含义的 ASCII 标点符号,不会进行转义的:;/?:@&=+$,#
  • encodeURIComponent(URIstring)
    对在 URI 中具有特殊含义的 ASCII 标点符号,也会进行转义的:;/?:@&=+$,#