网络传输五层模型
应用层(HTTP,FTP) —> 传输层(TCP,UDP)—> 网络层(IP协议)—-> 数据链路层 —-> 物理层
- 物理层:物理设备间传输数据
- 数据链路层:在通信的实体间建立连接
- 网络层:寻找地址
HTTP协议的发展
- HTTP/0.9:只有GET请求,没有头部信息,服务器发送完就关闭tcp连接
- HTTP/1.0:增加很多命令,增加status code和头部信息,以及支持缓存等
- HTTP/1.1:支持持久连接,增加host(在一台服务器跑多个服务)
- HTTP/2:所有数据都以二进制传输,头部压缩及推送功能
HTTP三次握手
seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号(ack表示对接收到的数据包表示确认), seq和ack是对应的
12345##客户端及服务器端发送http请求和响应需要创建 tcp连接来创建传输的管道##在HTTP/1.1中,可以在一个tcp连接里面发送多个请求,即持久连接client:SYNserver:SYN,ACKclient:ACKHTTP4次挥手
12345client:发送FIN标志位表示断开,以及seq=pserver:发送ACK,ack=p+1表示回应---server处理完自己的事情,比如还没发送完数据server:发送FIN标志,ACK以及seq=qclient:返回ACK,ack=q+1CORS跨域
同源政策:协议相同,域名相同,端口相同
可以在服务器端设置响应头部信息:Access-Control-Allow-Origin
注: 无论设置与否,其实浏览器已经接收到返回的内容了,只是浏览器没有检测到这个响应头部,所以做出了限制,并报错。
1234567891011121314151617#node.jsconst http = require('http')http.createServer((req,res) => {res.writeHead(200, {'Access-Control-Allow-Origin': 'http://google.com' //这里过滤条件为google域名})})//只能写一个这样的头部,设置多个域名可以用函数来实现(express.js)app.all('*', function(req, res, next) {if( req.headers.origin == 'https://www.google.com' || req.headers.origin == 'https://www.baidu.com' ){res.header("Access-Control-Allow-Origin", req.headers.origin);res.header('Access-Control-Allow-Methods', 'POST, GET');res.header('Access-Control-Allow-Headers', 'X-Requested-With');res.header('Access-Control-Allow-Headers', 'Content-Type');}next();});CORS预请求:相当于发送一个OPTIONS请求到服务器端验证
CORS默认只支持GET,POST,和HEAD方法
CORS默认允许的Content-Type:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
CORS遇到非默认允许的请求头也需要预请求的操作
12345设置预请求:1. 'Access-Control-Allow-Headers':'xxx' //设置了之后请求的时候设定的头部才会被允许#实际上先用OPTIONS请求,去获得服务器端的一个认可,然后再去实际请求。所以发送了两个请求2. 'Access-Control-Allow-Methods':'POST,PUT,DELETE'3. 'Access-Control-Max-Age':'1000' //表示1000秒内不需要发送预请求来验证缓存头Cache-Control
1'Catch-Control':'max-age=20000,no-cache' //用逗号分隔piblic:都可以进行缓存的操作
private:只有发起请求的浏览器可以缓存
no-cache:可以在本地进行缓存,但是要发送请求到服务器端去验证,是否可以使用,才可以使用
no-store:死活不可以缓存,永远拿新的
到期时间
- max-age = seconds :到期时间,最多缓存时间(浏览器专用)
- s-maxage=seconds:代理服务器专用
重新验证
must-revalidate:过了max-age之后,必须到源服务器端去请求,不能读取缓存
proxy-revalidete:代理服务器在过期后,也必须重新去新请求
no-transform:不能对资源进行转换
|
|
在Cache-Control头部设置了no-cache之后,需要资源验证
验证头:Last-Modified & Etag
Last-Modified:上次修改时间
配合请求头中的If-Modified-Since使用,服务器端收到这个请求头后,去对比文件的上次修改时间,如果一致,说明没有修改。返回304通知浏览器使用缓存
Etag:数据签名(对资源的内容生成唯一的签名,标记这个资源)
浏览器请求时会带上If-Match或者If-Non-Match请求头,值就是服务器端返回过来的Etag值,然后对比资源签名判断是否使用缓存,如果缓存就返回304状态码(304的意思not modified,没有修改)
cookie:键值对
服务器端生成,通过Set-Cookie响应头来设置。客户端下次就会自动带上Cookie请求头
属性:
- max-age(设置时间多长)和expires(到哪个时间点过期)设置过期时间
- Secure:只在https的时候发送
- HttpOnly:无法通过document.cookie来访问
- domain=xxx.com:xxx.com下的所有二级域名可以共享cookie
123#node.js'Set-Cookie':['id=123; max-age=20', 'abc=456;domain=test.com'] //通过数组设置多个cookie值//abc=456这个cookie值在a.test.com或者其他二级域名b.test.com都可以访问到HTTP长连接:复用tcp的连接
google调试工具network中有一个connection id,是tcp连接的id,可以看到是不是同一个tcp连接。
google浏览器默认可以并发6个tcp连接。当第7个请求发送时,要等前面6个有一个空出来才会去在这个tcp连接上通讯。
保持长连接:设置
'Connection':'keep-alive'
服务器端也可以设置
'Connection':'close'
:表示一个tcp请求完成之后,就关闭掉。所以所有的请求都会创建一个新的tcp连接,google调试工具中的connection id都是不同的,开销很大。数据协商
请求:Accept头部
- Accept:数据类型
- Accept-Encoding:
gzip,deflate,br
什么编码方式来传输。用来限制服务端对数据的压缩方式 - Accept-Language:
zh-CN,zh;q=0.9 , en;q=0.8
要求返回的信息语言、 q代表权重 - User-Agent:用判断返回pc端的页面还是移动端的页面
返回:Content头部
- Content-Type:对应请求的Accept
- Content-Encoding:用了什么数据压缩方式
- Content-Language
1234567数据类型格式:type/subtype 主类型/分类型image/pngimage/jpegtext/plain 显示源码text/html 显示html解析后的application/jsonapplication/javascriptRedirect重定向,在服务器端设置Location头,并返回302(临时重定向)或者301(永久重定向,除非用户自动清除浏览器,否则浏览器总是去跳转请求新的地址,不会去请求旧地址)
1'Location':'/xxx'CSP(Content-Security-Policy):内容安全政策
- 限制资源获取
- defalut-src:限制全局所有和连接请求有关的
- 定制:connect-src 、 img-src 、 script-src等
- 报告获取资源越权
123'Content-Security-Policy':'default-src http: https:' //只能通过http或者https的方式进行加载,网页里面嵌套js无法执行------------作用就是限制外链- 限制资源获取
Nginx代理:待了解
HTTPS:私钥&公钥