一个完整http服务的过程
1.在浏览器搜索框输入url,UI线程首先进行URL解析。 如果不是一个URL就交给搜索引擎进行搜索。如果是一个URL,就生成相应的请求信息,UI线程把他交给网络进程。
一个合法的URL包括协议,域名,端口号,请求资源路径,传参信息,hash值。
5.当发送http请求的时候会先在浏览器的缓存查找是否有有效的缓存(一般只缓存get请求),如果有缓存就进行缓存的判断,如果没有就开始解析url
http的<meta>里如果有cache-control no-cache,no-store就表示该Html资源不允许被缓存在浏览器中。
缓存有强缓存和协商缓存。
强缓存在 响应头 有关的字段是:
cache-control:max-age(缓存的秒数)
expires:GMT时间
如果以上两个有一个还没有过期就会直接使用浏览器的缓存数据,响应行的状态码是200。
如果以上两个都过期了那么就发送请求报文给服务器,进行协商缓存。
协商缓存在DNS,TCP,连接之后。
协商缓存的字段是:
(响应)ETag/(请求)if-Not-Match:hash校验值
(响应)Last-modified/(请求)if-modified-since:GTM时间
与服务器端的数据进行对比,如果没有进行修改,那么就返回状态码304继续使用缓存。如果数据进行了修改,就返回更新的数据并且更新缓存字段,状态码是200
2.首先是把域名转化成Ip地址。
首先在本地DNS缓存中递归查找。
分别是浏览器自身域名缓存区查找,操作系统域名缓存查找(ipconfig/displaydns),hosts文件(C:\Windows\System32\drivers\etc)查找。
没有找到 本地域名服务器就采用 迭代查询 依次查找根域名服务器,顶级域名服务器,权威域名服务器等。
3.建立TCP连接
- 客户端发送SYN = 1,序列号是seqX的数据包,表示想要建立连接。
- 服务器端收到后发送 SYN = 1,ACK = 1,ack = seqX+1, seqY的数据包。
- 客户端 接收到之后 发送ACK = 1,ack = seqY+1, seqX+1的数据包(也可以在数据部分携带数据)。至此三次握手完成,TCP建立了连接。
### 为什么要三次握手
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
客户端发送的连接请求如果在网络中滞留,客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
## TCP和UDP区别
- TCP面向连接,UDP是无连接的,即发送数据之前不需要建立连接
- TCP提供可靠的服务,即TCP连接传送的数据,无差错,不丢失。UDP尽最大努力交付,但是不保证数据的可靠性
- TCP只能是一对一,UDP可以一对一,一对多,多对一
建立TLS连接(4次)(如果是HTTPS协议的话)
TLS————RSA握手过程(传输层安全)
1.client hello
由客户端向服务器端发起加密通信的请求,包括客户端支持的TLS版本号,客户端随机生成的随机数(client random),客户端支持的密码套件列表。
2.server hello
服务器收到之后向客户端进行回应,确认TLS版本号,服务器生成的随机数(server random),确认的密码套件列表,服务器的数字证书。
3.客户端回应
客户端收到数字整数,通过浏览器或者操作系统中的CA的公钥,验证证书。证书没有问题就从证书中取出浏览器的公钥,使用公钥加密报文发送:
a.一个随机数(pre-master key)
b.加密通信算法改变通知
c.把之前发的所有内容做个摘要
4.双方各自使用已有的三个随机数和加密算法生成会话密钥。
5.服务器回应
算出会话密钥之后,向客户端发送:
a.加密算法改变通知
b.服务器握手结束通知.
c.把之前发的所有内容做个摘要
至此tls的四次连接结束,接下来发送的信息使用会话密钥来进行加密。
4发送http请求
http请求报文,分为三部分请求行(请求方法、url、协议、版本号),请求头,请求体。
## 基本方法
- GET:从服务器获取资源
- HEAD:在不获取资源的情况下了解资源状况(服务器响应中只返回头部)
- POST:在服务器创建资源
- PUT:在服务器修改资源
- DELETE: 在服务器删除资源
***GET和POST的区别
GET是向服务器请求获取资源(安全幂等的),POST是向指定url提交数据(不是幂等的)。
GET请求的参数包含在URL中,对外可见,所以安全性较差,POST请求的参数包含在请求体中,对外不可见,相对安全
浏览器会主动缓存GET请求的相关资源,但是对于POST,浏览器不会主动缓存,除非手动设置
GET请求的参数有长度限制,但是POST没有
GET请求在浏览器回退时是无害的,但是POST会重新发送请求
GET请求的参数,会被保存在浏览器的历史记录里面,但是POST不会
6.响应http请求
响应报文:响应行(协议、版本、状态码) 响应头 响应体
## 状态码(响应报文头部)
- 1xx 提供信息,表示已经接受,正在处理
100 continue主要用于提供信息
101 切换协议:如果服务器切换了协议会向客户端返回101
- 2xx 成功
200:ok
201:已创建
202:已接收
203:非权威内容
204:请求成功,但是无资源返回
205:重置内容
206:客户端进行了范围请求,服务器成功执行力这部分的请求,返回头部有Content-range指定了范围的实体内容
- 3xx重定向
300:用户请求了多个选项的资源
301:永久转移,资源已经被分配了新的URL,应该按照location部分的url重新保存
302:临时重定向
303:该资源存在着另一个URL,可以使用GET方法获取
304:没有修改(协商缓存命中时返回这个状态码)
305:使用代理
307:临时重定向
308:永久重定向
- 4xx客户端错误
400:报文存在语法错误
401:需要认证信息
403:被服务器拒绝
404:服务器上没有该资源
405:服务器禁止使用该方法
- 5xx服务端错误
7.浏览器解析html,并且请求代码里的资源
网络进程 通过IPC管道 把 html传给渲染进程。
渲染器进程的主线程把html进行解析,构造DOM数据结构。html首先通过词法分析把输入的HTML内容解析成多个标记,根据标记进行DOM树的构造,在构造的过程中会创建document对象,然后以document对象为根节点的DOM树不断进行修改,向其中添加各种元素。
HTML中会引入额外的资源:图片,css,js(这时候会利用http请求头中的connection:keep-alive属性,建立一次连接就可以请求多个资源。)。其中下载或者加载图片,css时不会阻塞html的解析(不会影响DOM树的构造),但是遇到js的加载的时候就会停止解析Html树,并且去下载执行js脚本(js可能会改变DOM树的结构)。
***async,defer***
一个普通的<script>标签的加载和解析都是同步的,会阻塞DOM的渲染,这也就是我们经常会把<script>写在<body>底部的原因之一,为了防止加载资源而导致的长时间的白屏,另一个原因是js可能会进行DOM操作,所以要在DOM全部渲染完后再执行。
script还有两种异步加载模式,async属性会异步加载,但是执行的时候依然会阻塞html解析(而且会乱序)。
defer是会使script异步加载,但是延迟执行(dom树构建完之后执行)
8 .浏览器渲染页面
解析完HTML页面就会获得一棵DOM树,然后主线程需要解析CSS,确定每个DOM节点的具体样式,其中CSS会有继承,就是子节点会继承父节点的样式。
然后进行layout布局:主线程通过遍历DOM树和样式来生成layout树,树上的每个节点都记录了坐标以及边框尺寸。(layout树和DOM树不是一一对应的,设置了display:none的DOM节点不会出现在layout树上,而在伪类before和after中content的元素会出现在layout树中)。
主线程遍历layout tree绘制一个记录表,这个表记录了绘制的顺序(生成图层,明确定位属性的元素、定义透明属性的元素、使用 CSS 滤镜的元素,出现剪裁的情况等,都拥有层叠上下文属性。),生成layer tree。
主线程把这些信息传递给合成器线程
合成器线程把每个图层分块传给栅格线程进行栅格化,当都完成栅格块之后会传给合成器一个图块(记录了栅格化的内容在内存的地址)。
合成器线程根据这些信息,会合成一个合成器帧,然后通过浏览器进程传给GPU进行渲染,展示到页面上。
*****回流和重绘
1.当改变一个元素的位置和大小、改变窗口大小的时候,会重新计算元素的位置,也就是从计算layout布局开始重复上面过程,这种行为就是回流。
2.当只改变一个元素的颜色属性的时候,不会触发重新布局,但是会触发样式计算和绘制,以及之后的过程,这种叫做重绘。
重排和重绘和js都会占用主线程,这样如果js占用时间过长就会导致页面卡顿,优化方法
1.是使用requestAnimationFrame(),这个方法会在每一帧被调用,这样就可以把js运行任务分成更小的任务块分布在每一帧上,在每一帧的时间用完前暂停js的执行,归还主线程,这样下一帧既可以按时执行布局和绘制。React的渲染引擎 React Fiber就是用这个api做的优化。
2.CSS动画有个属性transform,通过该属性的实现的动画不会进行布局和绘制,而是直接运行在合成器线程中和栅格化线程中,所以不会影响js执行。
transform:translate(x,y)
transform:scale(x,y)
transform:rotate(deg)
- 关闭连接
## TCP的四次挥手
- 客户端发送完数据后发送 FIN = 1的数据包。
- 服务器端接收到 发送 ACK = 1的数据包,客户端单方面断开连接。
- 服务器端完成数据传输后,发送FIN = 1的数据包。
- 客户端接收到后发送一个ACK = 1的数据包,等待一个2MSL的时间,然后关闭连接。
### 为什么等待2MSL
确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发送。
等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
网络结构
经典TCP/IP五层结构:应用层 传输层 网络层 链路层 物理层。
OSI七层结构:应用层,表示层,会话层,传输层,网络层,链路层,物理层。
- 应用层:就是应用服务程序,用于给用户提供各种服务,常见的协议有:DNS、 FTP、 HTTP等。
- 传输层:端到端的数据报的可靠传输,相关协议是TCP、UDP。
- 网络层:负责点到点的数据包的封装转发,寻找路由等,设备有路由器。相关协议有:IP、ICMP、IGMP、ARP。
- 链路层:负责点到点的数据帧的传送,设备有网桥,相关协议有:CSMA/CD、CSMA/CA等。
- 物理层:负责点到点的比特流的传输,设备有集线器,中继器。
CDN
是一种代理服务器,代理源站响应客户端的请求。可以实现负载均衡的作用。
HTTP协议的优缺点
超文本传输协议,用于在两台计算机之间传输文字图片或者超文本数据的约定和规范。
特点:
1.灵活可扩展,可以自定义头部键值对,传输的内容也可以是多样的。
2.请求应答模式
3.可靠传输(基于TCP)
4.无状态:有利于减少网络开销,提高传输速率,例如在直播行业。
缺点:
1.无状态:即使同一个客户端连续两次发送请求给服务器,服务器也无法识别这个同一个客户端发的请求,需要保存客户信息的时候不能实现。(用cookie解决)
2.明文传送:头部主要是文本形式,让信息暴露给外界,给攻击者带来了方便。
3.队头阻塞:http1.1是开启长连接时,共用一个TCP连接,当某个请求过长,其他请求就被阻塞。
HTTP报文结构
HTTP常见的请求头
POST /api/5632836/envelope/?sentry_key=39616798988c45a88e52d89282f7dcd1&sentry_version=7 HTTP/1.1
Host: 发起者的域名
Connection: keep-alive(长连接)
Content-Length: 18861(数据长度)
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Mobile Safari/537.36
Content-Type: text/plain;charset=UTF-8(发送报文数据的类型)
Accept: */*(接收数据的类型)
Origin: https://hejialianghe.gitee.io
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://hejialianghe.gitee.io/
Accept-Encoding: gzip, deflate, br(可接受的编码类型)
Accept-Language: zh-CN,zh;q=0.9
基本方法
- GET:从服务器获取资源
- HEAD:在不获取资源的情况下了解资源状况(服务器响应中只返回头部)
- POST:在服务器创建资源
- PUT:在服务器修改资源
- DELETE: 在服务器删除资源
响应头
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 18 Feb 2021 01:41:36 GMT
Content-Type: application/json
Content-Length: 41
Connection: keep-alive
access-control-allow-origin: https://hejialianghe.gitee.io(允许跨域的访问)
access-control-expose-headers: x-sentry-error, x-sentry-rate-limits, retry-after
vary: Origin
x-envoy-upstream-service-time: 0
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
HTTP2.0
相比HTTP1.1
1.头部压缩。如果同时发出多个请求,头部有相似的字段,协议会消除重复的部分。(HPACK算法:在客户端和服务器维护一张头信息表,所有字段都会存入,生成一个索引号,之后就只发索引号)
2.二进制形式。HTTP1.1还是纯文本形式,2版本全面采用二进制形式(头信息帧+数据帧)
3.数据流。2版本不是按顺序发送的,所以需要对数据包做标记,客户端还可以指定优先级。
4.多路复用。在一个连接里并发多个请求。
5.服务器推送,服务器可以主动向客户端发信息。
HTTPS补充
对称加密算法
AES ChaCha20
非对称加密算法:
用于加密会话密钥,一般有RSA和ECDHE。
RSA就是传统的加密方法,由服务器提供一个公钥,然后客户端用公钥加密会话密钥,最后服务器用私钥解密。但这种算法在服务器的私钥被窃取的时候就会失效。
ECDHE时使用ECC椭圆曲线特性计算公钥的。双方首先确认好使用哪种椭圆曲线和曲线基点G,然后各自生成一个私钥d,d*G生成公钥,然后交换公钥。根据椭圆曲线上满足乘法结合律和交换律生成共享密钥(会话密钥)。
摘要算法
就是哈希函数,常见的有MD5和SHA-1
浏览器存储
cookie
wangdoc.com/javascript/… HTTP cookie 是服务器发送到用户浏览器并且保存在用户本地的一小块数据,他会在浏览器下一次向同一个服务器发送请求时被报文携带一同发送过去。
cookie使无状态的HTTP协议可以记录状态信息。 根据同源策略,只要两个网址的域名相同就可以共享cookie。
分类
cookie总是保存在客户端,可以分为内存cookie和硬盘cookie。
内存cookie保存在内存中,由浏览器维护,浏览器关闭后就消失,所以也叫做非持久cookie。
硬盘cookie保存在硬盘里,当到了过期时间或者用户手动清除才会消失,也叫做持久cookie。
服务器端设置cookie
一般由服务器端设置cookie,在响应HTTP头中使用
Set-Cookie:foo=bar;Expires=Wed, 21 Oct 2015 07:28:00 GMT;Max-age=38000;Domain=example.com;path=/blog;Secure;HttpOnly。
foo是cookie的名,bar是cookie的值 只有访问example.com/blog时才会携带这个cookie,过期时间在expires和max-ages同时出现的时候以后者为准,Secure只有在https情况下才发送,HttpOnly是指 Cookie 无法通过 JavaScript 脚本拿到,只有浏览器发送HTTP请求的时候才可以携带。 Chrome新增了一个SameSite属性,用来防止CSRF攻击和用户追踪。
(CSRF攻击就是恶意网站获取了用户的cookie发送http请求。)
SameSite:Strict完全禁止第三方cookie,只有当前网页的url和请求目标一致的时候才会带上cookie。
SameSite:Lax,稍微放松了要求,导航到目标网址的Get请求可以携带cookie(例如在其他页面有个掘金链接,点击链接转到掘金的时候会携带cookie,所以这时候是登陆状态)
客户端发送cookie
浏览器向服务器请求的时候会携带相应cookie, 这时候会在请求头有这样的字段Cookie:foo=bar
读取当前的cookie
当没有设置HttpOnly时,可以通过document.cookie获取当前网页的所有cookie(防止了XSS攻击)
cookie缺点
- cookie会加在每个HTTP请求中,所以在请求的时候会浪费带宽。
- cookie大小设置在4KB左右。
- 可能会被拦截
storage
一般最大的存储是5M(不同浏览器会不同) 也遵守同源策略。
设置:window.localStorage.setItem('foo','3');
获取:window.localStorage.getItem('foo');
移除:window.localStorage.removeItem('foo');
sessionstorage
用于存储当前会话的数据,会存储在本地,不会频繁的往返于客户端和服务器端。
不可跨域,不可跨页面,一旦这个页面关闭,数据就会被清除。
localstorage
持久化的本地存储,存储在本地,也不会频繁来往。
只能存储字符串
同样不可跨域,但是可以跨页面,不能跨浏览器。
关闭浏览器也不会被清除,只有用户主动清除才可以。
indexedDB
容量大,nosql,同域共享。
indexedDB是一种内置在浏览器中数据库,是一种非关系型数据库,存储的数据格式JSON。
1、IndexedDB顾名思义是一种内置在浏览器中数据库,而且是一种非关系型的数据库,即不需要编写SQL语句去操作数据库,而且存储的数据格式是JSON。
2、IndexedDB不像我们平时服务器上使用的 NoSQL 数据库,IndexedDB没有表的概念,在IndexedDB中是叫object store,其实平时就可以把object store看做数据表。
3、IndexedDB的每次操作都是一个事务,每一个对数据库操作是在一个事务的上下文中执行的。
4、IndexedDB的每次数据库操作都需要先打开object store,再执行指定的操作,不能一直打开某个object store。
5、IndexedDB的所有操作都是异步的。
indexdb的具体使用
什么是同源策略
同源策略SOP是浏览器最核心的安全功能,如果缺少了同源策略,浏览器容易收到XSS、CSFR等攻击。
同源策略的目的是为了保护用户信息的安全,防止恶意的网站窃取数据。
同源策略主要针对三种行为
- Cookie,localStorage和indexDB。
- DOM节点和JS对象
- AJAX请求
什么是跨域
javascript出于安全方面的考虑,不允许跨域调用其他页面的对象。当一个请求url的协议、域名、端口有一个和当前页面url不同即为跨域。
www.juejin.com:8080/abcdef。
这是一个url。https是协议,www.juejin.com是域名,8080是端口号,abcdef是资源文件的编号。
为什么跨域危险还要跨域
因为一个公司内可能有多个不同的子域,这些子域之间需要互相调用资源。
需要调用一些外部的API,也会有跨域的问题。
允许跨域的实例
- script标签
- img标签 link标签 @font-face
- video、audio嵌入的资源
- iframe
- websocket
JSONP
利用script标签可以跨域的特性,网页动态增加一个script元素,向服务器请求JSON数据,服务器收到后把数据传到一个指定的回调函数中传回来。
缺点:只支持GET请求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
</head>
<body>
<h1>客户端</h1>
<script>
function f(str){
console.log(str);
}
</script>
<script src = "http://localhost:91?callback=f"></script>
</body>
</html>
let express = require('express');
let app = express();
app.use(express.static(__dirname))
app.listen(90);
let app2 = express();
app2.get('/',function(req,res){
let functionName = req.query.callback;
res.send(functionName+"('你好')");
})
app2.listen(91);
<script type="text/javascript">
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("http://ajax.googleapis.com/web?
v=1.0&q=apple&callback=result");
}
//自定义的回调函数result
function result(data) {
alert(data.responseData.results[0].unescapedUrl);
}
</script>
中间服务器代理proxy
通过中间件实现,浏览器有跨域限制,但是服务器之间没有跨域限制,所以中间件就是服务器。(服务器对数据进行了转发而已)。
前端部署的地址:127.0.0.1:8000 中间服务器(代理):127.0.0.1:8000。 目标服务器地址:127.0.0.1:8080
Ngnix反向代理
CORS(常用的)
跨域资源共享,是跨域AJAX请求的根本解决方法。因为跨域问题本来就是浏览器内部的限制,使用CORS在响应头上加上允许跨域的字段就可以实现跨域共享。(在服务器实现CORS接口)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
</head>
<body>
<h1>客户端</h1>
<script>
fetch("http://localhost:91/").then(
res => res.text()
).then(
data => {console.log(data)}
)
</script>
</body>
</html>
let express = require('express');
let app = express();
app.use(express.static(__dirname))
app.listen(90);
let app2 = express();
app2.get('/',function(req,res){
res.header("Access-Control-Allow-Origin","*");
res.send('你好');
})
app2.listen(91);
具体解释
CORS请求会分为两种:简单请求和非简单请求。
简单请求:
1.是GET/POST/HEAD请求
2.请求头中有
Accept
Accept-language
Content-language
last-event-id
Content-type: applaction/x-www-form-urlencoded、multipart/form-data、text/plain
浏览器发现请求是一个简单请求就会在请求头加上Origin:源域
如果不在许可范围内,服务器正常返回一个HTTP响应
浏览器在响应头中没有找到Access-Control-Allow-Origin就会抛出一个错误,并且拦截响应报文。
如果Origin在许可范围内,服务器在响应头中加入
Access-Control-Allow-Origin(*或者原来的域名)
Access-Control-Allow-Credentials:true(允许发送cookie)//同时在客户端设置xhr.withCredentials = true
非简单请求:
1.方法是PUT/DELETE
2.Content-type:application/json
当浏览器发现是非简单请求的时候会发送一条预检请求。
请求头中 :
OPTIONS:用于询问
Orgin
Access-Control-Request-Method:非简单请求的方法
Access-Control-Request-Headers:自定义的头部
服务器收到后检查相应字段,如果允许就做出回应
Access-Control-Allow-Orgin:所有允许的域
Access-Control-Allow-Methods:所有允许的方法
Access-Control-Allow-Headers:所有允许的头部
不允许的话会回应一个不带相应头部的报文,浏览器就会拦截然后抛出错误。
服务器通过预检请求后,客户端就可以进行正常的简单请求的流程
websocket
websocket是HTML5的一个持久化协议,实现了浏览器和服务器的全双工通信。Websocket和HTTP都是应用层协议,基于TCP,该协议不实行同源策略,只要服务器支持,就可以进行跨域通信。
XSS和CSRF
CSRF跨站请求伪造
未经用户许可,偷偷的使用用户名义,发送恶意请求的攻击。通常情况下借助用户cookie来骗取服务器信任。
CSRF(通常)发生在第三方域名。 CSRF攻击者(通常)不能获取到Cookie等信息,只是使用。
同源监测
CSRF Token: 需要服务端生成一个Token,然后放在页面中,页面提交请求的时候,带上这个Token。服务端把Token从Session中拿出,与请求中的Token进行比对验证。
Samesite Cookie属性:
XSS跨站脚本攻击
XSS本质是Html注入,攻击者在网站上注入恶意的js代码,对客户端页面进行篡改,进而窃取隐私数据比如cookie、session,或者重定向到不好的网站等。
不要相信用户输入: 对用户输入内容进行过滤。对特殊字符进行实体转义。
不要完全信任服务端:对服务端输出进行转义。
使用HttpOnly Cookie:将重要的cookie标记为httponly,这样就无法使用js代码获取cookie。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!