- 一、HTTP/1.1协议
- 3.浏览器发起HTTP请求的典型场景
- 4.基于ABNF语义定义的HTTP消息格式
- 5.OSI模型与TCP/IP模型
- 6.HTTP解决了什么问题
- 7.评估Web架构的七大属性
- 8.从五种架构风格推导出的HTTP的REST架构
- 9.chrome抓包工具
- 10.URI,与URL的区别
- 11.为什么要进行uri编码
- 12.请求行
- 13-14.响应码
- 15.管理代理服务器的长短连接
- 16.HTTP消息在服务器端的路由
- 17.代理服务器转发消息的相关头部
- 18.请求与响应的上下文
- 19.内容协商与资源表述
- 20.定长包体
- 21.不定长包体
- 22.HTML FORM表单提交的协议
- 23.range请求:断点续传、多线程下载的实现
- 24-25.Cookie、第三方Cookie与Session
- 26.同源策略
- 27.CORS(Cross-Origin Resource Sharing)跨域
- 28.条件请求
- 29-32.缓存
- 33.重定向
- 34.HTTP隧道
- 35.爬虫
- 36.HTTP协议基本认证
- 37.wireShark的使用
- 38.DNS解析
- 二、websocket协议
- 三、HTTP2
- 四、TLS
一、HTTP/1.1协议
3.浏览器发起HTTP请求的典型场景
调用浏览器引擎处理输入,敲下回车调用渲染引擎,发送网络请求,调用JS解析器,当DOM树CSS树构建好后用UI后端进行页面绘制。
一次HTTP协议完成的事情:
1.浏览器从URL中解析域名
2.根据域名查询DNS,获取对应IP地址
3.三次握手建立TCP连接(TLS/SSL握手)
4.构造HTTP请求,填充上下文至HTTP头部
5.发起HTTP请求,接收到携带HTML页面作为包体的HTTP响应
6.浏览器引擎解析响应,渲染包体至用户界面;根据超链接构造其他HTTP请求并发送请求….
HTTP协议:一种无状态的、应用层、以请求/应答方式运行的协议,它使用可拓展的语义和自描述信息格式,与基于网络的超文本信息系统灵活的互动。(RFC7230 2014.6)
无状态:请求间不互相依赖
请求/应答:c发送请求、s发送响应的模式
可拓展:c和s的http协议版本不一致任可通讯
自描述:响应含有对包体内容的描述,不需要额外发送请求获取包体的描述
4.基于ABNF语义定义的HTTP消息格式
ABNF(托冲巴科斯-瑙尔范式)分操作符、规则。
操作符:
空白字符:用来分隔定义中的各个元素,(SP代表空格)
选择/:表示多个规则都是可供选择的规则
值范围
序列组合():将规则组合起来,视为单个元素
不定量重复 m*n
可选序列:[]
规则:
5.OSI模型与TCP/IP模型

6.HTTP解决了什么问题
解决www信息交互必须面对的需求:
低门槛
可拓展性:巨大的用户群体、超长的寿命
分布式系统下的Hypermedia:大粒度数据的网络传输
Internet规模
无法控制的scalability
不可预测的负载、非法格式的数据、恶意消息
客户端不能保持所有服务器信息,服务器不能保持读懂个请求间的状态信息
独立的组件部署:新老组件并存
向前兼容
7.评估Web架构的七大属性
HTTP协议应当在以下属性中取得可接受的均衡:
1.性能Performance
2.可伸缩性Scalability:支持部署可以互相交互的大量组件
3.简单性Simplicity:易理解、易实现、易验证
4.可见性Visiable:对两个组件间的交互进行监视或者仲裁的能力,如缓存、分层设计等
5.可移植性Portability:在不同的环境下运行的能力
6.可靠性Reiliability:出现部分故障时,对整体影响的成都
7.可修改行Modifiability:对系统做出修改的难易程度,由可进化型、可定制性、可拓展性、可配置性、可重用性构成
8.从五种架构风格推导出的HTTP的REST架构
架构风格:某一类架构具有同类的约束
1.数据流风格Data-flow Styles
优点:简单性、可进化性、可扩展性、可配置性、可复用性
管道与过滤器Pipe And Filter,PF
每个Filter都有输入端和输出端,只能从输入端读取数据,处理后再从输出端产生数据
统一接口的管道与过滤器 Uniform Pipe And Filter,UPF
在PF上增加了统一接口的约束,所有Filter过滤器必须具备同样的接口
复制风格Replication Styles
优点:用户可察觉的性能、可伸缩性、网络效率、可靠性也可以得到提升
分层风格Hierarchical Styles
优点:简单性、可进化性、可伸缩性


scalability:分层-cs
简单性:分层-统一-无状态
可进化性:cs分离关注点
可重复性:分层
可见性:无状态
可移植性:分层
可靠性:无状态、缓存
移动代码风格Mobile Code Styles
优点:可移植性、可扩展性、网络效率

点对点风格Peer-to-Peer Styles
优点:可进化性、可复用性、可扩展性、可配置性
风格演变
9.chrome抓包工具
控制器
Preserve log:勾选后跳转新前面保存原页面的请求记录
过滤器
隐藏Data URLs:CSS/图片等小文件以base64形式嵌入到HTML中,以减少http请求数
属性过滤:
domain:仅显示来自指定域的资源,可以搭配通配符
has-response-header:显示包含指定HTTP响应标头的资源
is:使用is:running可以查找WebSocket资源,is:from-cache可查找缓存读出的资源
larger-than:显示大于指定大小的资源(以字节为单位)。将值设为1000等同于设置为1k
method:显示通过指定HTTP方法类型检索的资源
mime-type:显示指定MINE类型的资源
mixed-content:显示所有混合内容资源,或仅显示当前显示的资源
scheme:显示通过未保护HTTP(scheme:http)或受保护HTTPS(scheme:https)检索的资源
set-cookie-domain:显示具有set-cookie标头并且domain属性与指定值匹配的资源
set-cookie-name:显示具有set-cookie标头并且名称与指定值匹配的资源
set-cookie-name:显示具有set-cookie标头并且值与指定值匹配的资源
status-code:仅显示HTTP状态代码与指定代码匹配的资源
多属性间通过空格实现AND操作
请求列表(显示请求的属性及响应头的部分属性)
Name:资源名称
Status:HTTP状态代码
Type:请求资源的MIME类型
Initiator:发起请求的对象或进行,可以有以下值:Parser / Redirect / Script / Other,分别表示Chrome的HTML解析器 / HTTP重定向 / 脚本 发起的请求
Size:服务器返回的响应大小(包括头部和包体)
Time:总持续时间,从请求的开始到接收响应的最后一个字节
Waterfall:各请求相关活动的直观分析图
预览请求内容
查看头部/cookie/正文/时间详细分布
预览相应正文:查看图片
到处数据为HAR格式
查看未压缩的资源大小
浏览器加载时间(概览、概要、请求列表)
查看请求上下游:按住shift悬停,绿色是上游,红色的下游
请求时间详细分布
Queueing:在排队的时间
stalled:因排队而停止的时间
DNS Lookup:解析ip地址的时间
Proxy Negotiation:浏览器与代理服务器协商请求的时间
Request sent:正在发送请求
ServiceWorker Preparation:浏览器正在启动Service Worker
Request to ServiceWorker:正在将请求发送到Service Worker
Waiting(TTFB):浏览器正在等待响应的第一个字节。TTFB表示Time To First Byte(至第一字节的时间)。此事件包含1次往返时间及服务器准备响应所用的时间。
Content Download:浏览器正在接收响应
Receiving Push:浏览器正在通过HTTP/2服务器推送接收此响应的数据
Reading Push:浏览器正在读取之前收到的本地数据
10.URI,与URL的区别
url(uniform resource locator)表示资源的位置,期望提供查找资源的方法;
urn(uniform resource name)期望为资源提供持续的、与位置无关的标识方式,并允许简单地将多个命名空间映射到单个urn命名空间,例如磁力链接;
uri(uniform resource identifier)用以区分资源,是url和urn的超集,用以取代url和urn概念
总结:1.uri包含url和urn;2.URI强调的是给资源标记命名,URL强调的是给资源定位
uri组件:schema,authority,path, query,fragment
http://tools.ietf.org/html/rfc7231?test=1#page-7
11.为什么要进行uri编码
对分隔符 / uri保留字符/ 不安全字符/ 不在ascii码或在ascii码且不可显示的字符 进行转换
12.请求行
request-line = method SP request-target SP HTTP-version CRLF
请求行由method/ request-target/ HTTP-version组成。
method包括GET/ HEAD/ POST/ PUT/ DELETE/ CONNECT/ OPTIONS/ TRACE
HEAD:类似于GET方法,但服务器不发送body,仅用于获取head元数据,幂等方法(一次发送和多次发送获得响应一致)
CONNECT:建议tunnel隧道
OPTIONS:显示服务器对访问资源支持的方法
TRACE:回显服务器收到的请求,用于定位问题,已废弃(405)。
request-target的值为
1.origin-form = absolute-path[“?”query] 向origin server发起的请求,path为空时必须传递/ (很多情况是/)
2.absolute-form = absolute-URI 仅用于向正向代理proxy发起请求时,详见正向代理与隧道
3.authority-form = authority 仅用于CONNECT方法,例如CONNECT www.example.com:80/HTTP/1.1
4.asterisk-form = “*” 仅用于OPTIONS方法
version:HTTP0.9 / 1.0 / 1.1 / 2.0
13-14.响应码
status-line = HTTP-version SP status-code SP reason-phrase CRLF
状态行由HTTPversion/ status-code / reason-phrase组成。
成功状态码:
1xx:请求已接收到,需要进一步处理,HTTP1.0不支持
100 Continue: 上传大文件前使用,e.g.迅雷下载
101 Switch Protocols:协议升级使用,请求头携带Upgrade触发,如升级websocket或者http/2.0
102 Processing:服务器收到并正在处理请求,但无响应可用,防止超时处理。
2xx:成功处理请求
200 OK:成功返回响应
201 Created:有新资源在服务器端被成功创建
202 Accepted:服务器接收并开始处理请求,但请求未处理完成。
203 Non-Authoritative Information:代理服务器修改原响应时,会修改状态码为203
204 No Content:成功执行请求且不携带响应包体,通知客户端无需更新页面
205 Reset Content:成功执行请求且不携带响应包体,通知客户端需要更新页面
206 Partial Content:使用range协议时返回部分响应内容时的响应码
207 Multi-Stuatus:在WEBDAV协议中以XML返回多个资源的状态
208 Already Reported:为避免相同资源在207响应码下重复上报,使用208苦于使用父集合的响应码
3xx:重定向使用Location指向的资源或缓存中的资源
300 Multiple Choices: 资源有多种表述,通过300返回给客户端后由其自行选择访问哪种表述
301 Moved Permanently:资源永久性的重定向到另一个URI中
302 Found:资源临时的重定向到另一个URI中
303 See Other:重定向到其他资源,常用于POST/PUT等方法的响应中
304 Not Modified:客户端可以复用缓存
307 Temporary Redirect:类似302,但明确重定向后请求方法必须与原请求方法相同,不得改变
308 Permanent Redirect:类似301,但明确重定向后请求方法必须与原请求方法相同,不得改变
4xx:客户端出现错误
400 Bad Request:服务器认为客户端出现了错误,但不能明确判断
401 Unauthorized:用户认证信息确实或者不正确,导致服务器无法处理请求
407 Proxy Authentication Required:认证信息未通过代理服务器的验证
403 Forbidden:服务器理解请求的含义,但无权限执行
404 Not Found:服务器没有找到对应资源
410 Gone:服务器没有找到对应资源,且明确知道该位置永久找不到该资源
405 Method Not Allowed:服务器不支持请求行中的method方法
406 Not Acceptable:对客户端指定的资源表述不存在(例如对语言或者编码有要求),服务器返回表述列表
408 Request Timeout:服务器接收请求超时
409 Conflict:资源冲突,例如上传文件时目标位置已存在较新版本的资源
411 Length Required:请求含有包体且请求头未携带Content-Length属性,且不属于chunk类请求
412 Precondition Failed:条件请求:复用缓存时传递If-Unmodified-Since或If-None-Match头部不被满足
413 Payload Too Large/request Entity Too Large:请求包体超出服务器处理的最大长度
414 URI Too Long:请求的URI超出服务器能接收的最大长度
415 Unsupported Media Type:上传的文件类型不被服务器支持
416 Range Not Satisfiable:无法提供Range请求中指定的那段包体
417 Expectation Failed:对于Expect请求头部期待的情况无法满足时的响应码
421 Misdirected Request:服务器没有能力处理,认为该请求不应该发给它(501)
426 Upgrade Required:服务器拒绝基于当前HTTP协议提供服务,通过Upgrade头部通知客户端升级协议
428 Precondition Require:条件请求缺失头部,例如If-Match(412)
429 Too Many Requests:客户端发送请求速度过快(服务器限速,503)
431 Request Header Field Too Large:请求头大小超过限制(414)
451 Unavailable For Legal Reasons:RFC7725,法律原因资源不可访问
5xx:服务器端出现问题
500 Internal Server Error:服务器内容错误,且不属于以下错误类型
501 Not Implemented:服务器不支持实现请求所需要的功能
502 Bad Gateway:代理服务器连接不上源服务器
503 Service Unavailable:服务器资源尚未准备好处理当前请求
504 Gateway Timeout:代理服务器获取源服务器响应超时
505 HTTP Version Not Supported:请求使用的HTTP协议版本不支持
507 Insufficient Storage:服务器没有足够的空间处理请求
508 Loop Detected:访问资源时检测到循环
511 Network Authentication Required:代理服务器发现客户端需要身份验证才能获得网络访问权限
客户端接收到一个不认识的错误码,会按照同系列的00做处理。
15.管理代理服务器的长短连接
tcp编程看HTTP请求处理:
C5客户端调用write方法发送请求,C6客户端调用read方法等待读取响应
事务:一个请求及其对应的一个响应构成一个事务
短连接:一个连接执行一个事务 Connection:Close
长连接:一个连接执行多个事务 Connection:Keep-Alive
另外,代理服务器不转发Connection列出的头部
connection仅针对当前连接有效,也就是说一个链路中包含多次连接(如经过代理服务器),则只对当前连接有效。
陈旧代理器不识别Connection头部,直接透传,带来的影响:客户端和代理服务器的连接包含Connection:Keep-Alive头部,代理服务器透传,服务器收到Connection:Keep-Alive头部,返回与代理服务器连接也包含Connection:Keep-Alive头部,代理服务器透传,客户端收到Connection:Keep-Alive头部。此时,客户端与服务器均认为建立了长连接,且退化为的短连接没有关闭。第二次通讯时客户端复用长连接,代理服务器出错,因为短连接不能发起两次请求。
解决方案:Proxy-Connection代理Connection头部
陈旧代理服务器不能识别Proxy-Connection,透传给服务器;此时服务器收到Proxy-Connection则明白代理服务器不支持长连接,返回Connection:Close头部,且通知关闭连接。代理服务器同样透传至客户端,客户端同样明白是短连接,则不会复用长连接,而是新建短连接,且通知关闭上次的短连接。
新服务器能够识别,则会把Proxy-Connection替换成Connection:Keep-Alive头部,此时服务器也会返回Connection:Keep-Alive头部,构建长连接。
16.HTTP消息在服务器端的路由
host请求头部 Host = uri-host [“:” port]
HTTP/ 1.1规范要求,不传递Host头部则返回400错误响应码
为防止陈旧的代理服务器,发向正向代理的请求request-target必须以absolute-form形式出现(12课)
17.代理服务器转发消息的相关头部
HTTP头部X-Forwarded-For用于存储上游的IP,直到服务器取到请求,X-Forwarded-For存储着客户端(ADSL)和经过的代理服务器的IP
Max-Forwards头部:限制Proxy代理服务器的最大转发次数
Via头部:指明经过的代理服务器名称及版本
Cache-Control:no-transform 禁止代理服务器修改响应包体
18.请求与响应的上下文
请求的上下文:a
User-Agent 指明客户端的类型信息,服务器可以据此对资源的表述做抉择(比如ie6啥的就不给你发好东西)Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36表示兼容mozilla版本 渲染引擎 发布版本号
Referer 浏览器对来自某一页面的请求自动添加的头部(指从哪来,或者什么引起这次的请求)
Referer不会被添加的场景:来源页面的URI采用”file”或”data”的协议;当前页面http协议,来源页面https协议
服务器端常用于统计分析 缓存优化 防盗链等功能
From 主要用于网络爬虫,告诉服务器如何通过邮件联系到爬虫负责人
响应的上下文:
Server 指明服务器上所用软件信息,用于帮助客户端定位问题或统计数据
Server:openresty/1.13.6.2
Allow 告诉客户端,服务器上该URI对应的资源允许哪些方法的执行
Allow: GET, HEAD, PUT
Accept-Ranges 告诉客户端服务器上该资源是否允许range请求
Accept-Ranges: bytes
19.内容协商与资源表述
每个URI指向的资源可以是任何事物,可以有多种不同的表述,内容协商决定服务器端生成不同的http包体发给客户端。
内容协商的两种方式:
Proactive主动式内容协商——由客户端先在请求头部中提出需要的表述形式,而服务器根据这些请求头部提供特定的representation表述。
Reactive响应式内容协商——指服务器返回300 Multiple Choices或者406 Not Acceptable,由客户端选择一种表述URI使用。被动式协商的两次url可能不一致。
常见的协商要素
质量因子q:内容的质量、可接受类型的优先级
字符编码:由于UTF-8格式广为使用,Accept-Charset已被废弃
内容编码:主要指压缩算法 e.g. Accept-Charset:gzip,deflate,br
表述语言 e.g. Accept-Language:zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
国际化与本地化
internationalization,(i18n)
指设计软件时,在不同的国家、地区可以不做逻辑实现层面的修改便能够以不同的语言显示。
localization(l10n)
指内容协商时,根据请求中的语言及区域信息,选择特定的语言作为资源表述。
资源表述的元数据头部
媒体类型、编码 content-type:text/html;charset=utf-8
内容编码 content-encoding:gzip
语言 Content-Languange:de-DE,en-CA
20.定长包体
响应头Content-Length明确指明包体长度,优点:接收端处理方便。
若Content-Length大于实际包体,则报错,不能正确解析包体
若Content-Length小于实际包体,则只解析Content-Length指定的包体长度,剩余的仅接收不处理。
21.不定长包体
使用Transfer-Encoding头部指明使用Chunk传输方式(定长包体则没有这个头部),使用这个头部后Content-Length头部将被忽略。优点:1.基于长连接持续推送动态内容;2.压缩体积较大的包体时,不必完全压缩完(计算出头部)再发送,可以边发送边压缩;3.传输必须再包体传输完才能计算出的Trailer头部(放在chunk后再发送的头部,补充头部)。
Transfer-Encoding头部:Transfer-Enconding: "chunked",值还可以是”compress”/“deflate”/“gzip”/transfer-extension
chunked-body 由 chunk lase-chunk trailer-part CRLF 组成
chunk 由 chunk-size [ chunk-ext ] CRLF chunk-data CRLF 组成
因为chunk-size不需要很好的可见性,所以这里的chunk-size是十六进制的,而content-length是十进制的。chunk-size表明chunk有多少字节。
last-chunk = 1(“0”) [chunk-ext] CRLF 通常是一个0来表示chunk传输完毕
trailer-part = *(header-field CRLF) 可选的延迟头部,用于补充头部
trailer头部的传输:
TE头部:客户端再请求再声明是否接收Trailer头部 TE:trailers
Trailer头部:服务器告知接下来chunk包体后会传输哪些Trailer头部 Trailer:Date
以下头部不允许出现在Trailer的值中(需要放在一开始的头部):
用于信息分帧的首部(例如Transfer-Encoding和Content-Length)
用于路由用途的首部(例如Host)
请求修饰首部(例如控制类和条件类的,如Cache-Control,Max-Forwards或者TE)
身份验证首部(例如Authorization或者Set-Cookie)
Content-Encoding,Content-Type,Content-Range, 以及Trailer自身
MIME(Multipurpose Internet Mail Extensions),媒体类型"Content-Type:" type"/"subtype *(";"parameter),类和子类
e.g. Content-Type:text/plain;charset="us-ascii"
Content-Disposition头部(RFC6266)
e.g.Content-Disposition:attachment;filename="filename.jpg"
可选值有:
inline:指定包体是以inline内联的方式,作为页面的一部分展示
attachment:指定浏览器将包体以附件的方式下载
multipart/form-data:用于子消息体部分(form表单,22课),e.g.Content-Disposition:form-data;name="fieldName";filename="filename.jpg"
22.HTML FORM表单提交的协议
HTML:结构化标记语言(非编程语言),不能互动,本质上来说像笔记;
FORM表单:提供交互控制元件用来向HTTP协议提交信息,Submit控件用于提交HTTP请求,提交请求的关键属性:
action:提交发起HTTP请求的URI
method:提交时发起HTTP请求的http方法
GET:通过URI,将表单数据以URI参数的方式提交
POST:将表单数据放在请求包体中提交
enctype:在POST方法下,对表单内容在请求包体中的编码方式
application/x-www-form-urlencoded(默认):数据以’&’分隔键值对,’=’分隔键和值,url方式编码
multipart/form-data:boundary分隔符、每部分表述都有头部、请求头Content-Type:multipart/form-data、last boundary结尾。
multipart(RFC1521):一个包体中多个资源表述
整个请求的请求头Content-type指明这是一个多表述包体。Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryXX
Boundary分隔符的格式:0-69个字母数字或符号等,如上述
multipart包体格式(RFC822):
multipart-body = preamble 1*encapsulation close-delimiter epilogue
(preamble、epilogue最终都要去掉,不关注)
每部分包体格式encapsulation = delimiter body-part CRLF
delimiter = “—“ boundary CRLF (boundary前加”—“后加/r/n 就形成了delimiter)
body-part = fields (CRLF text)
filed可以是content-dsposition / content-type

最终分隔符close-delimiter
close-delimiter = “—“ boundary “—“ CRLF
23.range请求:断点续传、多线程下载的实现
步骤:
1.客户端明确任务:下载范围
2.下载文件的指定部分
3.下载完毕后拼装
HTTP Range规范(RFC7233)
允许服务器基于客户端啊的请求只发送响应包体的一部分,客户端自动将多个片段的包体组合成完整的体积更大的包体——支持断点续传、多线程下载、视频播放器的实时拖动
服务器通过Accept-Range头部表示是否支持Range请求,e.g.Accept-Range:bytes表示支持,Accept-Range:none表示不支持
发送请求时,客户端通过Range头部传递请求范围,e.g.Range:bytes=0-499``Range:bytes=0-100,101-200 (可以发多重范围multipart)
Range条件条件请求:客户端在获取后续资源时不能保证之前的资源未过期,所以需要发送range条件请求,使用If-Unmodified-Since或If-Match : ETag或 If-Range=entity-tag/HTTP-date/ETag/Last-Modified。满足则返回206 Partial Content,不满足则返回412 Precondition Failed
服务器响应:
206 Partial Content : 同时还会返回Content-Range头部,表示当前片段包体在完整包体的位置,e.g.Content-Range:bytes42-1233/1234``Content-Range:bytes42-1233/**表示未知完整长度
412 Precondition Failed:条件请求不满足
416 Range Not Satisfiable:请求范围不满足实际资源大小
200 OK:服务器不支持Range请求,返回完整包体和200 OK
多重范围与multipart
响应:Content-Type:multipart/byteranges; boundary=xxx,包体如图,和22课类似。
24-25.Cookie、第三方Cookie与Session
cookie的定义:保存在客户端、由浏览器维护(服务器生成)、表示应用状态的HTTP头部(RFC6265, HTTP State Management Mechanism),可以存放在内存或磁盘中。
过程:
1.客户端发起请求;
2.服务器生成Cookie在响应中通过Set-Cookie头部告知客户端Set-Cookie: session-id=123456;
3.客户端得到Cookie后,后续请求都会自动将Cookie头部携带至请求中Cookie: session-id=123456;
Cookie头部头部可以放多个name/value名值对;Set-Cookie头部只能传递一个名值对,但可以有多个Set-Cookie头部。
Cookie头部定义 cookie-string = "Cookie:" OWS cookie-string OWS OWS表示可选的SPcookie-string = cookie-pair *(";"SP cookie-pair)cookie-pair = cookie-name"="cookie-value
Set-Cookie头部定义 set-cookie-header = "Set-Cookie:"SP set-cookie-stringset-cookie-string = cookie-pair *(";"SP cookie-av)
cookie-pair同上,cookie-av可选属性,如下:
cookie-pair:
expires-av:cookie倒日期sane-cookie-date后失效 "Expires="sane-cookie-date
max-age-av:cookie经过 DIGIT秒后失效,优先级高于expires `”Max-Age=” DIGIT<br />domain-av:指定cookie可用于哪些域名,默认可以访问当前域名“Domain=”domain-value<br />path-av:指定Path路径下才能使用cookie“Path=”path-value<br />secure-av:只有使用TLS/SSL协议(https)才能使用cookie“Secure”<br />httponly-av:只能HTTP请求访问cookie“HttpOnly”`
设计及限制:
cookie不应超过4kb,估对于复杂的存储需求不够用;
HTTP请求中Cookie明文传递不安全,HTTPS安全
登录场景下的session用法(与cookie对比)
1.客户端向服务器发送post请求,携带账号密码;
2.服务器与持久化数据库(e.g. mysql)做比对,通过则继续;
3.将具有时效性的登陆状态(sessionId:session)写入内存数据库(缓存,e.g. redis);
4.服务器向客户端返回响应200 OK,且携带session:Set-Cookie:session=sessionId
5.客户端收到Set-Cookie头部,进行cookie的存储;
6.客户端再次请求,自动携带Cookie头部:Cookie:session=sessionId
7.服务器收到session,与redis服务器进行比对;
与Cookie的异同:
1.初次与服务器比对完后,cookie是直接返回名值对;但session是把value存到redis,并建立sessionId:value的映射,返回session:sessionId;
2.两者的实现原理都是借助Set-Cookie 、Cookie头部。
应用状态与资源状态
应用状态:应由客户端管理
e.g.浏览器在哪页
资源状态:应由服务器管理
e.g.如数据库仲存放的数据状态,例如用户的恩如信息
HTTP请求的状态
有状态的请求:服务器端保存请求的相关信息,每个请求可以使用以前保留的请求相关信息
e.g. 服务器session机制使服务器保存请求的相关信息;cookie使请求可以携带查询信息,与session配合完成有状态的请求。
无状态的请求:服务器能够处理的所有信息都来自当前请求所携带的信息
e.g. 服务器不会保存session信息;请求可以通过cookie携带
REST架构是无状态的
第三方cookie:a网站引用了b网站的资源,浏览器允许b网站的响应设置Set-Cookie头部,从而用户日后访问b网站,其能知悉用户曾访问过a网站。
因为cookie保存着应用状态,携带了用户的隐私信息。为了避免不同域名下脚本互相访问,以产生用户的安全问题,浏览器启用了同源策略。
26.同源策略
由于允许存在站点a引用站点b的情况存在,所以发向站点b请求并不是用户自愿发出的,仅仅是a网站请求的下游请求。由此就带来风险:
CSRF(Cross-Site-Request-Forgery)跨网站攻击:b网站的脚本通过浏览器访问a网站,由于此时浏览器有cookie,所以能够自动通过鉴权,由b网站的脚本访问到a网站。防御措施:
referer:只有来自当前域名的请求才允许通过鉴权
隐藏token:a网站的响应携带隐藏的token,下次请求需要携带这个隐藏的token才可通过鉴权
27.CORS(Cross-Origin Resource Sharing)跨域
CORS:站点A允许站点B的脚本访问其资源,必须再HTTP响应中显式告知浏览器:站点B是被允许的
请求分类:简单请求、复杂请求
简单请求:GET/HEAD/POST方法之一;仅能使用CORS安全的头部:Accept、Accept-Language、Content-Language、Content-Type;Content-Type的值只能是:text/plain、multipart/form-data、application/x-www-form-urlencoded
复杂请求:不满足上述条件
简单请求的跨域访问
1.请求中携带Origin头部告知来自哪个域
2.响应中携带Access-Control-Allow-Origin头部表示允许哪些域
3.通过则浏览器放行(其实响应已经正常回到服务端了,但浏览器不放行则不渲染,也不解析报文)
复杂请求的跨域访问
1.预检请求头部,只能发送OPTIONS请求
Access-Control-Request-Methods:告知服务器接下来请求用的方法
Access-Control-Request-Headers:告知服务器接下来请求携带的头部
2.预检请求响应
Access-Control-Allow-Methods:告知客户端后续请求允许使用的方法
Access-Control-Allow-Headers:告知客户端后续请求允许携带的头部
Access-Control-Max-Age:告知客户端该响应的信息可以缓存多久
Access-Control-Expose-Headers:告知浏览器哪些响应头部可以客户端使用,默认只有Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma可以使用
Access-Control-Allow-Origin:告知浏览器允许哪些域访问当前资源
Access-Control-Allow-Credentials:告知浏览器是否可以将Credentials暴露给客户端使用
3.延续简单请求的跨域访问
28.条件请求
资源R可被定义为随时间变化的函数MR(t) (资源与时间的函数)
静态资源:创建后任何时刻值都不变,例如指定版本号的库文件
动态资源:其值随时间而变化,例如某新闻站点首页
优点:
1.实现了在无需人为设定类型或者实现方式的情况下,同一资源多种不同来源的信息
2.基于请求特性进行内容协商,使资源的渲染延迟绑定
3.允许表述概念而不是具体的Representation,故资源变化时不用修改所有链接
条件请求:由客户端携带条件判断信息,而服务器与执行条件验证过程成功后,再返回资源的表述。
常用场景:使缓存的更新更有效率(如304复用)、断点续传对之前内容的验证、多个客户端并行修改同一资源,防止某一客户端的更新被错误丢弃
验证器:根据客户端请求中携带的相关头部,以及服务器资源的信息,执行两端的资源验证。
强验证器:服务器上的资源表述只要有变动(例如版本更新或者元数据更新),那么以旧的验证头部访问一定会导致验证不过;
弱验证器:服务器上资源变动时,允许一定程度上仍然可以验证通过(例如一小段时间内仍然允许缓存有效)
验证器响应头部:
Etag
强验证器: Etag: "xyzzy"
弱验证器: Etag: W/"xyzzy"
Last-Modified
表示对应资源表述的上次修改时间(区别于Date头部,Date头部是响应包体生成时间,所以Last-Modified不晚于Date的值)
条件请求头部:
If-Match = ““/ 1#entity-tag
If-None-Match = ““/ 1#entity-tag
If-Modified-Since = HTTP-date
If-Unmodified-Since = HTTP-date
If-Range = entity-tag/HTTP-date
缓存更新:
客户端发送请求,服务器返回携带Etag头部的响应,客户端存储tag;之后的请求客户端携带If-Match/If-None-Match/If-Modified-Since/If-Unmodified-Since头部,服务器返回304Not Modified或200 OK。
增量更新:Range断点续传
客户端发送请求,服务器返回携带Etag头部的响应,客户端存储tag;之后的请求客户端携带If-Match/If-None-Match/If-Modified-Since/If-Unmodified-Since头部,服务器返回206 Partial Content或412Precondition Failed。在412时,客户端还需再次发起请求重新获取,也可以使用If-Range头部避免两次请求(省略了如果412再次发起请求)
更新丢失问题:乐观锁
两个客户端同时修改服务器资源,需要条件请求。初次请求时获取Etag,提交时携带Etag,如果Etag相同说明期间资源没有被修改可以提交,反则返回412。
服务器处理条件请求的规则:Nginx
1.判断if-unmodified-since,不返回412则继续;
2.判断if-match,不返回412则继续;
3.判断if-modified-since,不返回200则继续;
4.判断if-none-match,返回200或304..
29-32.缓存
HTTP缓存:为当前请求复用前请求的响应
目的:减少时延,降低带宽消耗
私有缓存:仅供一个用户使用的缓存,通常只存在于如浏览器这样的客户端上
共享缓存:可以供多个用户使用的缓存,存在于网络中负责转发消息的代理服务器(对热点资源常使用共享缓存,以减轻源服务器的压力,并提升网络效率,但Authentication响应不可代理。)
过期的共享缓存处理
客户端发送请求,代理服务器发现资源过期,向源服务器发送条件请求,源服务器返回200或304给代理服务器,代理服务器返回资源给客户端。
缓存实现示意图
上半部分,Nginx通过红黑树实现快速查询的字典结构,key又schema、path、host构成。
下半部分,缓存使用链表进行存储,因为存储的空间有限,使用链表方便将最先存入的缓存移除。
判断缓存是否过期
缓存新鲜度:s-maxage>max-age>Expires>预估过期时间
*预估过期时间:由于大多响应没有携带缓存头部,但浏览器也会进行缓存且预估一个过期时间。
Age头部和current_age的计算
Age头部:自源服务器发出响应(或验证过期缓存),到使用同一缓存的响应发出时 经过的秒数
current_age的计算:p30

Cache-Control头部
cache-control的值大致分为三类:
红色类:头部需要跟等号和十进制数字,如max-age=36000
黑色类:直接使用
蓝色类:既可以直接使用,也可以跟等号指定生效范围
请求中的头部:
max-age:告诉服务器,客户端不会接受Age超出max-age的缓存
max-stale:告诉服务器,即使缓存不新鲜,但只要不超出max-stale仍可使用。如max-stale后不跟具体值,则表示无论过期多久都可使用。
min-fresh:告诉服务器,Age至少经过min-fresh秒后缓存才可使用
no-cache:告诉代理服务器,不能直接使用已有缓存作为响应返回,除非带着缓存条件到上游服务器得到304验证返回码才可使用现有缓存(协商缓存:可以保证请求获取到最新的内容)
no-store:告诉代理服务器不要对该请求的响应缓存(实际上不少代理服务器都不遵守该规定)
no-transform:告诉代理服务器不要修改消息包体的内容
only-if-cached:告诉服务器仅能返回缓存的响应,若没有缓存则返回504 Gateway Timeout
响应中的头部:
must-revalidate:告诉客户端一旦缓存过期,必须向服务器验证后才可使用
proxy-revalidate:与must-revalidate类似,但它仅对代理服务器的共享缓存有效
no-cache:告诉客户端不能直接使用缓存的响应,使用前必须在源服务器验证得到304返回码(协商缓存)。如果no-cache后指定头部,则只对含有该头部的请求/响应生效
max-age:告诉客户端缓存Age超出max-age则缓存过期
s-maxage:与max-age相似,但仅针对共享缓存,且优先级高于max-age和Expires
public:表示无论私有缓存或者共享混村,皆可将该响应缓存
private:表示该响应不能被代理服务器作为共享缓存使用。若private后指定头部,则告诉代理服务器含有指定头部的响应生效。
no-store:告诉所有下游节点不能对响应进行缓存
no-transform:告诉代理服务器不能修改消息包体的内容
什么样的HTTP响应会缓存
请求方法可以被缓存理解
响应码可以被缓存理解(404、206也可以被缓存)
响应与请求头部没有指明no-store
响应中至少应含有以下头部中的1个或多个:
Expires、max-age、s-maxage、public
响应中没有明确指示过期时间的头部但响应非常明确也可以缓存(预估过期时间)
如果缓存在代理服务器上,则还需不含有private或Authorization才可以缓存
旧头部PragmaPragma:no-cache 和 Cache-Control:no-cache 意义相同
使用缓存作为当前请求响应的条件
URI是匹配的(以uri为key)
缓存中的响应允许当前请求的方法使用缓存
缓存中的响应Vary头部指定的头部必须与请求中的头部相匹配e.g.
请求头部:Accept-Encoding:br
缓存响应的头部: Vary:Content-Encoding Content-Encoding:gzip
当前请求以及缓存的响应都不包含no-cache头部(有则需要发请求,响应304后才可复用缓存)
缓存的响应必须满足以下三者之一:
新鲜的 / 告知可以使用过期响应(Cache-Control: max-stale=60) / 过期且但验证响应304
缓存更新频率不同的资源
HTML缓存时间非常短,或不缓存。CSS JS缓存时间长,使用版本号来解决不同版本的问题
Warning头部:对响应码进行补充(缓存或包体转换)
验证请求
若缓存响应中含有Last-Modified头部,则请求使用If-Unmodified-Since、If-Modified-Since、If-Range头部
若缓存响应中含有Etag头部,则请求使用If-Match、If-None-Match、If-Range头部
33.重定向
URI重定向的场景:
提交form表单成功后需要显示内容页
站点从http迁移到https
站点部分uri发生了变化,但搜索引擎或流量入口只收录了老uri
站点正在维护,需要给用户展示不同内容
站点更换新域名
重定向流程:
浏览器正常访问,服务器返回重定向响应码。浏览器接收到后读取头部Location头部的值,获取新URI再跳转访问该页面。Location头部可以是绝对路径,也可以是相对路径,需要浏览器进行拼接。
永久重定向:表示资源永久性变更到新的URI,可以缓存
301:重定向请求用GET方法
308:重定向请求与原请求保持同样的方法和包体
临时重定向:表示资源只是临时变更到新的URI,不缓存
302:重定向请求用GET方法
303:不表示资源变迁,而是用新URI为原请求服务,重定向请求用GET方法
307:重定向请求与原请求保持同样的方法和包体
重定向死循环:重定向次数达到阈值时,浏览器不再请求,报ERR_TOOMANY_REDIRECTS
34.HTTP隧道
HTTP Tunnel隧道:用于通过HTTP链接传输非HTTP协议格式的消息,常用于穿越防火墙,传递SSL消息。
链路:
1.客户端向网关(隧道端点)发起CONNECT请求;
2.网关向服务器打开TCP连接;
3.连接建立,服务器向网关返回报文,网关向客户端返回报文;
4.此时,建立起原始数据的任意双向通道,直到连接关闭为止;在此传输的内容不用遵循HTTP规范,也不再是HTTP请求/响应模式,而思双向传输。
回归12课:CONNECT请求携带authority-form = authority(authority指定源服务器),表示建立隧道。
35.爬虫
网络爬虫模拟人类使用浏览器浏览、操作页面的行为,对互联网的站点进行操作。网络爬虫获取到一个页面后,会分析出页面里的所有URI,沿着这些URI路径递归地遍历所有页面,因此被称为爬虫(Web crawler)。
对待爬虫的2种态度:
欢迎:
SEO,搜索引擎优化:
合法的优化:sitemap、title、keywords、https等;
非法的优化:利用PageRank算法漏洞,e.g. 访问量大的站点(商家)指向目标站点(客户),来使目标站点的搜索排名靠前。
拒绝访问:
图形验证码 ==== 打码平台
爬虫优先算法:
深度优先:优先爬取一条分支的所有页面
广度优先:优先爬取同等级页面
比较:深度优先复用长连接,解决TCP拥塞控制
常见头部:
User-Agent:标识是哪类爬虫(是谁在爬
From:提供爬虫机器人管理者的邮箱地址
Accept:告知服务器爬虫对哪些资源类型感兴趣
Referer:相当于包含了当前请求的页面URI
robots.txt:告知爬虫哪些内容不应爬取
User-agent:对哪些机器人做出以下规范
Disallow:禁止访问特定目录
Crawl-delay:访问间隔秒数(防止占用过多对外资源
Allow:抵消Disallow指令
Sitemap:指出站点地图的URI
36.HTTP协议基本认证
HTTP基本认证:一种基本的验证框架,被绝大部分浏览器所支持。
流程:
1.浏览器发起请求;
2.服务器发现需要认证,返回401 Unauthorized,同时带有头部WWW-Authenticate: Basic realm="Access to the staging site"
3.浏览器弹出自带的弹窗给用户输入账号密码,发送GET请求,带有头部Authorization: Basic XXX,其中XXX是 账号:密码 的base64编码
4.服务器接收请求进行验证,返回200或403 Forbidden(也可能是401)
*账号密码以明文传输,所以如果不使用TLS/SSL传输则有安全问题。
37.wireShark的使用
ACK报文:在TCP层面的,用于确认请求已收到的报文。
TCP UDP根据ip和端口号跟踪到一个会话
38.DNS解析
一个用于将“域名”与服务器ip地址进行映射的数据库。
递归查询:(以www.baidu.com为例)先根据com查询根域名服务器、再根据baidu查询权威服务器,最后查询www。
DNS报文在UDP上传输
二、websocket协议
39.WireShark捕获过滤器
BPF过滤器:Wireshark捕获过滤器
Berkeley Packet Filter,在设备驱动级别提供抓包过滤接口,多数抓包工具都支持该语法





RST报文:不正常地关掉了
40.WireShark显示过滤器





41-48.WebSocket
41.定义
websocket是建立在TCP之上的,全双工通讯的协议(rfc6455)。websocket通过HTTP1.1的101状态码进行握手后就可以双向通讯,利用ping-pong心跳机制维持链接(详见p48)。
chrome浏览器通过选择WS或者过滤器输入is:running过滤显示websocket链接
42.约束
实时性很好;通过负载均衡可以随意增减服务器,可伸缩性也很好;
但帧传递是有状态的(详见p45),牺牲了可见性;通过代理服务器分发消息,需要一套消息分发系统,牺牲了简单性。
HTTP长连接的维持基于简单的定时器(常见为65秒),超时之后断开连接。
WebSocket基于ping/pong心跳机制维持,超时服务器发出ping帧,客户端返回pong帧,表示维持链接。
兼容HTTP协议:握手时,客户端发送请求需要携带Upgrade头部通过服务器进行协议升级,协议升级成功服务器返回101响应码,握手完成。
端口默认80或443。代理服务器也可以支持websocket协议。
websocket协议是在web约束下暴露TCP(传输层协议)给上层(应用层)
1.HTTP协议头部存放元数据,而websocket的元数据由应用层定义
2.websocket基于帧,HTTP、TCP基于流
3.基于浏览器的同源策略模型,可以使用Access-Control-Allow-Origin头部
4.基于URI、子协议支持同主机同端口的多个服务
43.帧格式
帧格式示意图,帧首部的前两个字节(红框)必然是描述
FIN:1表示消息结束,0表示消息没结束(消息与帧见p45)
RSV:默认为0,仅当使用extension扩展时,由扩展决定其值。
opcode:
持续帧:
0:继续前一帧(并不知道是文本还是二进制,只是和前面是一样的)
非控制帧:
1:文本帧(UTF-8)
2:二进制帧
3-7:非控制帧的保留
控制帧:
8:关闭帧
9:心跳帧ping
A:心跳帧pong
B-F:控制帧保留
payloan len:有三种长度(见p45)
[frame-masking-key]:32位,用于掩码
payload-data:8位*n
44.HTTP1.1升级websocket

子协议、扩展协议、CORS跨域可选项
握手:客户端发送消息,服务器回应消息,完成之后即握手成功
红色:必选
绿色:随机数,必选,服务器需要根据随机数生成base64编码
蓝色:跨域相关

服务器返回的随机数生成规则:
1.将客户端给的随机数和GUID拼接(GUID是RFC4122定义的一串固定的字符串)
2.进行SHA1编码,编码完后是十六进制的数字
3.进行base64编码,编码完后直接作为Sec-WebSocket-Accept头部返回
45.
46.



将payload四位一次,进行与masking-key的XOR操作(四个位置的十六进制数据和masking-key都是八位的,比如e924ff5d)
47.
HTTP1.1定时器,定时器内没有响应则停止
心跳帧可穿插到数据帧
ping是服务器发起 pong是客户端响应
48. ping/pong维持机制
控制帧中的关闭帧:在TCP连接之上的双向关闭。
发送关闭帧后,不能再发送任何数据;接收到关闭帧后,不再接收任何到达的数据。
关闭顺序:先关闭websocket再关闭tcp。所以运行过程中,如果tcp意外中断,websocket也会关闭。

三、HTTP2
49.HTTP1.1的问题
高延迟:并发数量有限,且一个连接只能同时处理一个事务
头部大:无状态需要每次携带大量头部
不支持推送消息:需要长轮询
50.HTTP2新特性
传输数据量的大幅减少:以二进制方式传输、标头压缩
多路复用及相关功能:消息优先级-可以无需等待源源不断地发送请求和接收响应
服务器消息推送:并行推送
51.wireshark解密TLS/SSL报文
SSL(secure socket layer)和TLS是在HTTP2(应用层协议)之下的会话层,进行报文的加密。

加密算法AES128
52.基于TCP的HTTP2 (h2c)
53.基于TLS的HTTP2(h2)



改进:
54.帧、消息、流的关系
连接Connection:一个TCP连接,包含一个或者多个Stream
数据流Stream:一个双向通讯数据流,包含1条或者多条Message
消息Message:对应HTTP/1中的请求或响应,是业务层面的概念,不体现在传输中,包含一条或多条Frame
数据帧Frame:最小单位,以二进制压缩格式存在HTTP/1中的内容
数据帧分header帧和data帧,而header帧和data帧共同组成原来HTTP/1中的一条message
传输中无序,接收时组装:同一个stream必须有序,跨越stream可以无序
概念对比:
HTTP/1.x的概念:Start Line、 Header、 Body
HTTP/2的概念:Length、 Type、 Flags、 Stream ID、 Payload
55.stream流ID
9字节标准帧头部:帧长度Length24bit、帧类型Type8bit、Flags8bit 标志位1bit Stream Identifier31bit
Stream ID的作用:
1.实现多路复用(多个stream复用一个connection):同个connection可以并发传输多个Stream,但同一个Stream的frame必须有序;STTINGS_MAX_CONCURRENT_STREAMS控制并发Stream数。
2.推送依赖性请求的关键:由客户端建立的流必须是奇数,由服务器建立的流必须是偶数。
3.流状态管理的约束性规定:新建立的流ID必须大于曾经建立过的状态为opened或者reserved的流ID;在新建立的流上发送帧时,意味着将更小ID且为idle状态的流置为closed状态;Stream ID不能复用,长连接耗尽ID应创建新连接。
4.应用层流仅影响数据帧:Stream ID为0的流仅用于传输控制帧;在升级过程中,101响应码通过ID为1的流返回,且返回后该流进入half-closed(local)状态。
56.帧格式:帧类型及设置帧的子类型(帧类型汇总)
帧长度Length:
默认只能接收0-2^14-1字节的长度,需要接收2^14-2^24的长度,需要接收端的设置帧的SETTING_MAX_FRAME_SIZE的identifier设置,详见p56
帧类型Type:
HEADER帧详见p57-60
PRIORITY帧详见p64
RST_STREAM帧详见p63
SETTING帧详见p56
PUSH_PROMISE帧详见p61
WINDOW_UPDATE帧详见p65
设置帧(stream id为0的帧)
设置帧的内容可以看作多块组成,每一块都分为identifier(16bit)和value(32bit),设置的类型分为以下:
SETTING_HEADER_TABLE_SIZE (0x1):通知对端索引表的最大尺寸(单位字节)
SETTING_ENABLE_PUSH (0x2):value设置为0时可金庸服务器推送功能,1表示启用推送功能
SETTING_MAX_CONCURRENT_STREAMS (0x3):告诉接收端允许的最大并发流数量
SETTING_INITIAL_WINDOW_SIZE (0x4):声明发送端的窗口大小,用于stream级别流控(详见p),初始值为2^16-1
SETTING_MAX_FRAME_SIZE (0x5):设置帧的最大大小,初始值2^14字节
SETTING_MAX_HEADER_LIST_SIZE (0x6):知会对端头部索引表的最大尺寸,单位字节,基于未压缩前的头部
57-60.HPACK
http2通过HPACK算法对头部进行压缩,HPACK由RFC7541规范,主要有三种压缩方式:静态字典、动态字典、压缩算法:Huffman编码(最高压缩比8:5)。
静态字典可以将常用的头部及值编译成index进行传输,减少压缩空间,不常用或多种值的头部使用Huffman编码进行传输;动态字典则是复用之前HTTP的头部,在原有头部数据上进行修复。
Huffman编码:出现概率较大的符号采用较短的编码,概率较小的符号采用较长的编码。
Huffman树的构造过程:计算各字母的出现概率;出现频率最小的两个字符(子树)构成子树,左小右大,左0右1。例子:

头部帧结构如下:
Pad Length是帧通用头部;Header Block Fragment是HTTP的头部:
如果一个帧放不下完整头部,可在HEADER帧或PUSH_PROMISE帧后跟着持续帧(type=0x9)补充完整的HTTP头部。
静态字典和动态字典的index整数编码:以5位前缀为例,编写1337
前三位xxx,只编写5位,后5位最大为31,1337-31=1306;第二行编写1306/128的余数,且第一位为1;第三行编写有多少个128。下图为名称的示例,值跟在名称后。
前缀的位数与场景有关:
场景分为两个方面,大体为:1.header和value都以索引编码、header索引编码value字典编码、header和value都以字典编码;2.进入动态表、不进入动态表、永远不进入动态表;其中header和value都以索引编码不需要考虑动态表,所以情况如下3*3-2=7种所示。
1.名称和值都在索引表(字典)中:7位前缀,首位送1;
2.名称在索引表,值不在且需要传入动态字典:6位前缀,首位送01;
3.名称和值都不在索引表,且都需要传入动态字典:6位前缀,首位送01,名称的位置送000000;
4.名称在索引表,值不在且不需要传入动态字典:4位前缀,首位送0000;
5.名称和值都不在索引表,且都不需要传入动态字典:4位前缀,首位送0000,名称的位置送0000;
6.名称在索引表,值不在且永远不传入动态字典:4位前缀,首位送0001;
7.名称和值都不在索引表,且都永远不传入动态字典:4位前缀,首位送0001,名称的位置送0000;
名称不在索引表,名称需要字面编码,字典编码跟在前缀行后。
修改动态表的大小:
1.在header帧中直接修改:5位前缀,首位送001,后紧跟着max size(数值31过大参考上面的整数编码)
2.在SETTING帧中修改,SETTINGS_MAX_HEADER_LIST_SIZE(0x6)
61.服务器的主动推送
推送的价值:提前将资源推送至浏览器缓存。
特性:推送可以基于已经发送的请求,例如客户端请求html,主动推送js文件
实现方式:
推送资源必须对应一个请求
请求由服务器端PUSH_PROMISE帧发送(PUSH_PROMISE帧和HEADER帧都是描述资源,但HEADER帧用于传递HTTP头部,PUSH_PROMISE帧用于描述服务器主动推送资源的描述)
响应在偶数ID的STREAM中发送(请求和响应都是服务器发给浏览器的)
例子:
Stream1发送HTML文件前发送PUSH_PROMISE帧,告知即将发送的资源信息;在Stream2中并发发送资源。
PUSH_PROMISE帧
type=0x5,只能由服务器发送。可在设置帧中SETTINGS_ENABLE_PUSH(0x2)中禁用(详见p56)。
Promised Stream ID:发送资源的Stream ID
Header Block Fragment:资源的描述
62.Stream的状态变迁
Stream特性:
一条TCP连接上,可以并发存在多个处于OPEN状态的Stream
客户端或服务器都可以创建新的Stream
客户端或服务器都可以首先关闭Stream
同一条Stream内的Frame帧是有序的
从Stream ID的值可以分辨PUSH消息:所有为发送HEADER/DATA消息而创建的流,从奇数开始递增;所有为发送PUSH消息而创建的流,从偶数开始递增
Message特性:
一个HTTP Message由1个HEADER(可能含有0或多个持续帧)及0或多个DATA帧构成
HEADER消息同时包含HTTP/1.1中的start line与headers部分
取消HTTP/1.1中的不定长Chunk消息
Stream流状态变迁:
符号:
H:HEADERS帧
PP:PUSH_PROMISE帧
ES:END_STREAM标志位 (该标志位值为1的帧)
R:RST_STREAM帧
流状态:
idle:起始状态
half closed 单向关闭——-remote不再接收数据帧/ local不再发送数据帧
1 处于idle状态,发送/接收header帧,变迁为open状态
1.1 处于open状态,发送/接收END_STREAM标志位值为1的帧,变迁为half closed(local/remote)状态;然后接收/发送ES或RST_STRAM帧,或发送/接收RST_STREAM帧,进入closed状态
1.2 处于open状态,发送/接收RST_STREAM帧,直接进入closed状态
2.处于idle状态,发送/接收PUSH_PROMISE帧,变迁为reserved状态,接收/发送HEADERS帧,进行half closed(local/remote)状态。
第二种情况是服务器主动推送消息的情形。
63.RST_STREAM帧错误码
HTTP2多个流共享同一连接,RST帧允许立刻终止一个未完成的流
RST_STREAM帧不使用任何flag,其格式是32bits,主要用于传输错误信息,如下:
NO_ERROR(0x0):没有错误。GOAWAY帧优雅关闭连接时可以使用此错误码
PROTOCOL_ERROR(0x1):检测到不识别的协议字段,或是版本不匹配
INTERNAL_ERROR(0x2):内部错误
FLOW_CONTROL_ERROR(0x3):检测到对端没有遵守流控策略
SETTINGS_TIMEOUT(0x4):某些设置帧发出后需要接收端应答,在等待时间内没有收到应答
STREAM_CLOSED(0x5):当Stream已经处于半关闭状态不在接收Frame帧时又接收到新的Frame帧
FRAME_SIZE_ERROR(0x6):接收到的Frame Size不合法(超出帧长度,详见p56)
REFUSED_STREAM(0x7):拒绝先前的Stream流的执行
CANCEL(0x8):表示Stream不再存在
COMPRESSION_ERROR(0x9):对HPACK压缩算法执行失败
CONNECT_ERROR(0xa):连接失败
ENHANCE_YOUR_CALM(0xb):检测到对端的行为可能导致负载的持续增加
INADEQUATE_SECURITY(0xc):安全等级不够,与TLS相关
HTTP_1_1_REQUIRED(0xd):对端只能接受HTTP/1.1协议
64.STREAM优先级(PRIORITY帧)
在PRIORITY帧(帧格式详见57-60)中设置当前Stream的优先级。其中,与优先级相关的格式如下:
E:Exclusive标志位:确定新增的stream与原来stream的优先级关系。e.g.
B/C流依赖A流,新增D流依赖A流。
当E为0时,新权重结构:B/C/D流依赖A流;当E为1时,新权重结构:D流依赖A流,B/C流依赖D流。
Stream Dependency:当前流依赖于某个流(即当某个流发生完才到当前流)
weight:权重,取值范围1到256,默认16。如果两个流依赖同个流,则根据各自权重占总权重比分配内存和流量。
65.不同于TPC的流量控制(WINDOW_UPDATE帧)
HTTP1.1使用tcp传输层的流量控制,HTTP2使用应用层流量控制。原因:HTTP2的多路复用技术(多个stream共用一个connection)意味着多个stream必须共享TCP层的流量控制,会互相干扰,可能造成stream阻塞。
代理服务器内存有限,上下游网速不一致时,通过流控管理内存。
HTTP2的留空既针对单个stream,也针对整个tcp连接:
客户端和服务器都具备流量控制能力
单向流控制:发送和接收独立设定流量控制
以信用为基础:接收端设定上限,发送端应当遵循接收端发出的指令
流量控制窗口(流或者连接)的初始值为65535字节
只有DATA帧服从流量控制,HEADER帧/PRIORITY帧/PUSH_PROMISE帧/SETTING帧以及WINDOW_UPDATE帧(流控帧本身)不服从流量控制
WINDOW_UPDATE帧格式:
不使用任何flag,窗口范围1至2^31-1字节
当stream id为0时表示对连接流控,否则为对stream流控
流控仅针对直接建立TCP连接的两端,所以代理服务器不需要透传WINDOW_UPDATE帧
流控制窗口:窗口大小由接收端告知,窗口随着DATA帧的发送而减少
SETTINGS_MAX_COUNCURRENT_STREAMS控制并发流:仅统计open和half-close状态的流(不包含用于推送的reserved状态),超出限制后报错PROTOCOL_ERROR
66.HTTP2与gRPC框架
gRPC:支持多语言编程、基于HTTP2通讯的中间件。
67.HTTP2的问题
TCP及TCP+TLS建链握手过多的问题
TCP握手过程(三次握手):
1.client发起包
2.server回包和ACK
3.client发ACK,而且可以携带数据
TCP+TLS握手过程:
1.client发起包
2.server回包和ACK
3-4.协商握手套件信息
5-6.交换公钥信息,生成共享加密密钥
(上述是TLS1.2 TLS1.3将3-6的两次往返合成一次往返)
TCP的队头阻塞问题:
不同的流并发是作为一个TCP报文发出的,经过操作系统的处理,处理成一个个IP报文,IP报文转发时无序,但到达时有序。如果转发过程中丢失了一个IP报文,则其之后的会堵塞不处理,直至触发TCP定时重发机制,补上该报文为止。
原因:TCP必须保证资源有序到达
TCP由操作系统内核实现,更新缓慢
68.QUIC协议
HTTP2的模型:IP(网络层)+TCP(传输层)+TLS1.2(表示层)+HTTP2(应用层)
HTTP3的模型:IP(网络层)+UDP(传输层)+QUIC协议+HTTP2 API(应用层)
QUIC协议实现了多路复用(原来在HTTP2中)、TLS1.3协议、拥塞控制(原来在TCP中)
HTTP3的连接迁移:允许客户端更换IP地址、端口后,任然可以复用前连接
解决队头阻塞问题:UDP报文没有队列概念(图为TCP和UDP)

解决握手繁琐问题-1RTT完全握手:
1.TCP(传输层)和TLS(表示层)进行合并;
2.TLS1.2中的繁琐套件更换为只支持有限的套件,减少了沟通套件参数的一次RTT。
由此,一次RTT沟通公钥之后就可以生成密钥了。
0RTT恢复会话握手:复用之前的密钥信息直接发送数据,但没有前项保密功能(即最后一次破密后,之前的报文即可解密)。
69.七层负载均衡
1.HTTP协议转换:
request line起始行:URL重写、method变换、http version版本变换(适配老旧服务器)
header头部:名值转换(http2的索引表)、对header属性进行修改
body包体:压缩算法转换、按固定协议格式对内容进行转换
2.WAF防火墙(Web Application Firewall)
request line请求行:检查URL及query参数是否合法(如SQL注入)、method是否何方(如阻止TRACE方法)、htto version版本是否合法
header头部:检查header项是否符合应用场景要求
body包体:对于FORM表单等通用格式做过滤
3.反向代理:选择负载低的服务器实现负载均衡
4.缓存功能:热门信息保存在负载均衡中
总结:
HTTP2的四个新特性:多路复用、协议升级(TLS)、HPACK(解决无状态的繁杂头部问题)、PUSH_PROMISE帧的主动推送。
四、TLS
70.TLS协议工作原理
设计目的:身份验证、保密性、完整性
内容:
Record记录协议:对称加密
Handshake握手协议:验证通讯双方身份、交换加解密的安全套件、协商加密参数
TLS安全密码套件解读:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
ECDHE 密钥交换算法
RSA 身份验证算法
AES_128_GCM 对称加密算法、强度、工作模式
SHA256 签名hash算法
71-72.对称加密算法
对称加密原理:XOR异或操作
对明文和密钥进行异或运算得到密文,密文和密钥进行异或运算也能得到明文(同一位的三个数中,只能有3个或1个0,即1是成对的,所以能够根据现有的两个位推出另外一个位)。
填充padding
Block cipher分组加密:将明文分成多个等长的Block模块,对每个模块分别加密。
当最后一个明文Block模块长度不足时,需要填充。
填充方法:
位填充:以bit位位单位来填充
字节填充:以字节为单位来填充
补零:所有字节填充0
ANSI X9.23:空位都补0,最后一个字节表示填充了多少字节
ISO 10126:随机字符填充,最后一个字节表示填充了多少字节
PCKS7(RFC5652,AES所使用):所有字节填充相同内容:共多少字节需要填充
分组工作模式block cipher mode of operation:允许使用同一个分组密码密钥对多余一块的数据进行加密
ECB模式Electronic codebook:
直接将明文分解为多个块,对每个块独立加密
问题:无法隐藏数据特征
CBC模式Cipher-block chaining:
每个明文块先与前一个密文块进行异或后,再进行加密(与密钥异或)
问题:加密过程串行化
CTR模式Counter:
通过递增一个加密计数器以产生连续的密钥流
问题:不能提供密文消息完整性校验
验证完整性:hash函数—-MAC(Message Authentication Code)
发送方将密文和密钥通过hash算法生成MAC,传输密文的同时传输MAC。接收方接收到密文密钥和MAC后,使用相同的hash算法生成MAC,对比生成和接收的MAC是否一致,一致则密文密钥完整。
GCM:CTP+GMAC
73.详解AES算法
AES常用填充算法;PKCS7,常用分组工作模式:GCM。
Rijndael密码算法明文分组长度可变,密钥长度也可变。明文分组长度和密钥长度彼此独立地确定为128、192、256bits,因而Rijndael算法有 9种不同的版本,而迭代次数与明文分组长度和密钥长度有关。
| 轮数(Round) | 明文分组长度128bits | 明文分组长度192bits | 明文分组长度256bits |
|---|---|---|---|
| 密钥长度128bits | 10 | 12 | 14 |
| 密钥长度192bits | 12 | 12 | 14 |
| 密钥长度256bits | 14 | 14 | 14 |
NIST选中Rijndael算法作为AES算法,限定了明文分组为128bits,而密钥长度可为128、192、256bits,因而实际上AES有三个版本:AES-128、AES-192、AES-256,相应的迭代轮数为10轮、12轮、14轮。
每列固定4bytes,即32bits。明文限定128bits的情况,明文分组固定4行4列;密钥长度分为128bits、192bits、256bits,所以密钥矩阵固定4行,但列数可以为4、6、8。
初始状态矩阵:由一个分组的每个字节重新排列组成,每4个字节组成一列,从左到右依次排成一列列。由此明文初始状态矩阵是4x4矩阵,而密钥初始矩阵根据算法强度分为4x4、4x6、4x8的矩阵。
步骤:
1.把明文按照128bit(16字节)拆分成若干个明文块,每个明文块是44矩阵
2.按照选择的填充方式来填充最后一个明文块
*3.每一个明文块利用AES加密器和密钥,加密成密文块
4.拼接所有的密文块,成为最终的密文结果
AES加密流程C=E(K,P),cipher,key,plaintext,E是每轮算法,每轮密钥皆不同。轮数分为三类:初始轮、普通轮和最终论。
初始轮(第0轮):
AddRoundKey 轮密钥加
普通轮
SubBytes 字节替代
ShiftRows 行移位
MixColumns 列混合
AddRoundKey 轮密钥加
最终轮
SubBytes 字节替代
ShiftRows 行移位
AddRoundKey 轮密相加
AddRoundKey 轮密钥加:
矩阵中每一个字节都与该次回合密钥(round key)做XOR运算;每个子密钥由密钥生成方案(密钥扩展)产生。
SubBytes字节替代:提供非线性变换能力,避免简单代数性质的攻击
透过一次非线性的替换函数(S盒,一个16×16的矩阵),用查找表单方式把每个字节替换成对应的字节。
矩阵中每个元素(8bits)的前4bits指定S盒的行,后4位指定S盒的列,将查询到的值替换掉原来位置的值,实现非线性替换。
ShiftRows 行移位
将矩阵中的每个横列进行循环式移位:第一行不变、第二行循环左移1个字节、第三行循环左移2个字节、第四行循环左移3个字节。
MixColumns 列混合
行移位后得到的矩阵和固定矩阵进行矩阵相乘。
密钥扩展
74.非对称加密和RSA算法
非对称加密:根据算法生成一对密钥,加密者使用公钥生成密文,接收者使用私钥解密得到明文。也可以反过来,数字签名的应用:证书发行者使用私钥进行加密,任何人可以使用公钥进行解密得到签名信息。
RSA算法生成公私钥的过程:
1.随机选择两个不相等的质数p和q
2.计算p和q的乘积n(明文小于n,n很大是保证难以破译的关键,因此对n做因式分解得到p和q很困难)
3.计算n的欧拉函数v=φ(n)=(p-1)(q-1)
4.随机选择一个整数k(1
6.公钥:(k,n)
7.私钥:(d,n)
RSA算法加解密流程:
加密: c = (m^k)mod n
解密: m=(c^d)mod n
75.基于openssl
https://www.openssl.org/
基于openssl生成私钥:openssl genrsa -out private.pem (private.pem是私钥)
从私钥中提取公钥:openssl rsa -in private.pem -pubout -out public.pem(public.pem是公钥)
加密文件:openssl rsautl -encrypt -in hello.txt -inkey public.pem -pubin -out hello.en
解密文件:openssl rsautl -decrypt -in hello.en -inkey private.pem -out hello.de
76-77.非对称加密应用
PKI体系(Public Key Infrastructure 公钥基础设施):管理公钥
公钥证书的生成和验证:
生成:
1.个人信息使用特定hash算法生成hash值;
2.PKI体系使用私钥对hash值进行加密,生成密文;
3.PKI体系将个人信息、密文、公钥整合为公钥证书。
验证:
1.用户(浏览器)收到公钥证书拆分为用户信息和密文;
2.利用公钥将密文解密为明文hash值,个人信息使用特定hash算法生成hash值(明文);
3.两个hash值进行对比,相同则通过。
证书类型:
域名验证(domain validated, DV)证书
组织验证(organization validated, OV)证书
扩展验证(extended validation, EV)证书
不用DH的RSA+AES密钥交换:
1.client发起hello;
2.server传递公钥;
3.客户端生成密钥(对称),并使用server的公钥进行加密为密文,传递回server;
4.server用私钥对密文进行解密,得到密钥(对称),之后的通讯使用对称密钥进行加密通讯。
问题:没有前向保密性——即如果获取了server的私钥,即可破解进行用于加密报文的对称密钥,对已保存的报文进行破解。
DH密钥交换协议:
DH是一种在TLS/SSL握手中交换密钥的算法,允许双方在完全没有对方任何预先信息的条件下通过不安全信道创建起密钥。过程:
1.client发起hello
2.server保有私钥1,传递公钥1;
3.client保有私钥2,传递公钥2;
4.client基于私钥2和公钥1、server基于私钥1和公钥2,利用DH算法,生成一致的密钥,该密钥用于加密报文。
实例:
公开信息:随机数g、p,公钥A,公钥B
1.发起方生成随机数g、p,私钥a;计算并传递公钥AA = ga mod p,传递g、p
2.接收方生成私钥b,计算并传递公钥BB = gb mod p
3.双方基于各自的私钥和对方的公钥计算出一致的密钥K。
发起方:K = Ba mod p,接收方:K = Ab mod p
问题:1.中间人伪造攻击,2.DH存在大量乘法和需要长密钥位数导致计算速度慢
解决方法:PKI体系,2.ECC椭圆曲线
78-79.ECC椭圆曲线及ECDH
定义:
椭圆曲线表达式:y2 = x3 + ax +b,其中4a3 + 27b2 !== 0,又称威尔斯特拉斯椭圆曲线函数(Weierstrass ‘s elliptic functions)

特性:+运算
P + Q = R,几何意义:PQ直线与曲线的交点的X轴镜像是R
满足交换律和结合律(为后面的双方根据各自的私钥和对方的公钥计算出一致的密钥 提供理论基础)
代数计算方法:
1.计算斜率m
2.计算R点坐标
ECC关键原理Q=K.P(Q是由K个P进行+运算得到的)
已知K与P,正向运算快速
已知Q与P,计算K的逆向运算非常困难(安全性保证)
其中Q是公钥,K是密钥,P是公共参数
ECDH密钥交换协议:
DH密钥交换协议使用椭圆曲线后的变种,优点:比DH计算速度快、同等安全条件下密钥更短。步骤:
公开信息:选定曲线、曲线上的共享P点
1.发起方选定大整数Ka作为私钥,基于选定曲线及P点,计算并传递公钥QaQa = Ka·P,传递选定曲线和P点;
2.接收方选定大整数Kb作为私钥,基于选定曲线及P点,计算并传递公钥QbQb = Kb·P
3.双方根据各自私钥和对方公钥生成统一密钥Qb·Ka=(X,Y)``Qa·Kb=(X,Y),其中X威对称加密的密钥。原理:Qb·Ka = Ka·(Kb·P) = Ka·Kb·P = Kb·(Ka·P) = Qa·Kb
ECDH与DH区别:根据私钥计算公钥及生成统一密钥时,使用ECC曲线代替mod算法,避免大量乘法造成的开销。
X25519曲线:Montgomery curve蒙哥马利曲线的变种
Montgomery curve蒙哥马利曲线:By2= x3 + Ax2 + x
X25519曲线:y2= x3 + 486662x2 + x
80.TLS1.2与TLS1.3的ECDH协议
TLS1.2的通讯过程:验证身份、达成安全套件共识、传递密钥、加密通讯。步骤:
1.client hello,发送支持的安全套件列表
2.server hello,选择安全套件
3.发送证书
4.server发送公钥
5.client发送公钥
6.生成共同密钥
1-3、4-5共两个RTT,其中client Hello是明文传输,安全套件是如椭圆曲线
FREAK攻击:对明文的client hello进行修改,安全套件列表中删除安全性高的安全套件,留下安全性低的以供选择,降低破解难度。解决:TLS1.3大大减少了支持的安全套件,删除了安全性低的安全套件,如openssl1.1.1中仅支持五种安全套件:(详见p70)TLS13-AES-256-GCM-SHA384TLS13-CHACHA20-POLY1305-SHA256TLS13-AES-128-GCM-SHA256TLS13-AES-128-CCM-8-SHA256TLS13-AES-128-CCM-SHA256
TLS1.3中的密钥交换
client事先生成多种安全套件的公私钥,待握手时,
1.client hello发送安全套件列表及所有公钥
2.server hello选择安全套件及公钥
3.双方生成共同密钥
其中,1-2共1个RTT。
81.握手的优化
session缓存:以服务器生成的session ID为依据
client hello时携带session ID,如果server判断session有效则复用缓存的密钥信息,在server hello后,Change Cipher Spec通知client复用上次的缓存。
session ticket:
不再缓存session,基于集群共同分享的独有密码,对密钥进行加密,加密后的信息叫session ticket(即encrypted session key)。client hello时携带该信息,集群解密后得到密钥。
TLS1.3的0-RTT握手:第一次握手即携带请求数据。
0-RTT重放攻击:中间服务器挟持了报文,不进行解密,但可以在之后某个时机进行重发。
优化方案:设置合适的过期时间
82.量子通讯与BB84协议
TLS回顾:通讯双方在身份验证(PKI)的基础上,协商(DH系列)出一次性的、随机(TLS中间件)的密钥。
使用分组对称加密算法,基于有线长度的密钥讲任意长度的明文加密传输。
QKD与光偏振原理
量子密钥分发quantum key distribution,简称QKD。QKD:如果有第三方试图窃听密码,则通信的双方便会察觉。(原理:不同方向的光波通过光栅时通过率是不相同的——通过概率,固定系统数通讯的概率是固定的,如果第三方插入,则导致概率的变化。)
BB84协议:
传输者和接收者针对每一bit都随机选择光栅,只有当两者选择同一种光栅,才能接收到该bit的信息。由此,接收到的信息bit数和总信息bit数的比例关系即是正确率。接收者将信息和光栅传回给传输者,传输者根据正确率确定是否有第三方监听,且进行密钥纠错(告诉传输者那些位是正确的)。






