# 08.详解HTTP协议
# 一、HTTP简介
# 1.HTTP
HTTP:超文本传输协议,是一种通信协议;允许超文本标记文档从Web
服务器传送到客户端的浏览器中。
简单:传输html
文件的协议。
Web:是一种基于超文本和HTML
的、全球性的、动态交互的、跨平台的分布式图形信息系统。
http
是无状态协议,这保证了它的高效。Cookie
和Section
的出现使http
在保持高效的情况下,能够记住状态;
# 2.URI与URL
URI
可分为URL
,URN
或同时具备locators
和names
特性的东西;URN
的作用就好像一个人的名字,URL
就像这个人的地址;- 换句话说:
URN
确定了东西的身份,URL
提供了找到它的方式;
URL是URI的一种,不是所有的URI都是URL;URI唯一地标识了身份,URL给出了访问机制(http/ftp/telnet等)
# 二、状态码
# 1xx:接收的请求正在处理
# 2xx:请求正常处理完毕
状态码 | 状态码英文名称 | 描述 |
---|---|---|
200 | OK | 请求已成功,请求所希望的响应头或数据体将随此响应返回 |
202 | Accepted | 已接受,已经接受请求,但未处理完成 |
204 | No Content | 请求处理成功,但是返回的响应报文中不包含实体的主体部分 |
206 | Partial Content | 该状态码表示客户端进行了范围请求, 而服务器成功执行了这部分的GET 请求。 响应报文中包含由 Content-Range 指定范围的实体内容。 |
# 3xx:重定向
状态码 | 状态码英文名称 | 描述 |
---|---|---|
301 | Moved Permanently | 永久重定向,请求的资源已被永久的移动到新的URI ,返回信息会包括新的URI ,浏览器会自动定向到新的URI 。今后任何新的请求都会使用新的URI (比如某的网站域名已更改,访问旧网址会自动跳转到网址) |
302 | Found | 暂时重定向,与301 类似。但资源只是临时被移动,客户端应继续使用原有的URI |
303 | See Other | 该状态码表示由于请求对应的资源存在着另一个URI , 应使用 GET 方法定向获取请求的资源。与 302 区别在于303 希望用户使用GET 访问新的URI ,而302 可以使用POST 访问新的URI |
304 | Not Modified | 该状态码表示客户端发送附带条件时(If-Match , If-ModifiedSince 等), 服务器端允许请求访问资源, 但未满足附带的条件。 此时返回, 304 状态码, 不包含任何响应的主体部分。另一种理解:所请求的资源没有更改,可以使用缓存 |
# 4xx:客户端错误
状态码 | 状态码英文名称 | 描述 |
---|---|---|
400 | Bad Request | 客户端请求报文语法错误,服务器无法理解 |
401 | Unauthorized | 表示发送的请求需要有通过HTTP 认证(BASIC 认证、DIGEST 认证) 的认证信息 |
403 | Forbidden | 服务器理解客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页) |
# 5xx:服务器错误
状态码 | 状态码英文名称 | 描述 |
---|---|---|
500 | Internal Server Error | 服务器端内错误或Web 应用存在 bug 或某些临时的故障,导致无法完成请求 |
502 | Bad Gateway | 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求 |
503 | Service Unavailable | 表明服务器暂时处于超负载或正在进行停机维护, 现在无法 处理请求 |
# 三、HTTP首部
# 1.HTTP请求和响应报文
# 1.1HTTP请求报文
# 1.2.HTTP响应报文
可见HTTP报文一共有四种首部字段(请求头):请求首部字段、响应首部字段、通用首部字段、实体首部字段;
# 1.3.示例
在chrome
的开发者调试工具当中,从请求报文和响应报文分各抽出了一部分,形成了三部分:
General:
Request Headers:
Response Headers:
# 2.请求首部字段
# 2.1.Accept
作用:浏览器端可以接受的媒体类型;
若想要给显示的媒体类型增加优先级, 则使用 q
来额外表示权重值,用分号(;)
进行分隔。权重值q
的范围是0~1
(可精确到小数点后3
位) ,且1
为最大值。不指定权重q
值时,默认权重为 q=1.0
。
当服务器提供多种内容时,将会首先返回权重值最高的媒体类型。
# 2.2.Accept-Charset
作用:用来通知服务器用户代理(浏览器)支持的字符集及字符集的相对优先顺序。
图Accept-Charset字段中的值:
Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
中的unicode-1-1;q=0.8
是一个整体,表示unicode编码优先级为0.8,小于默认的iso编码优先级(默认q=1);不要以为分号(;)为分割符,其实逗号(,)才是分割符
# 2.3.Accept-Encoding
作用:用来告知服务器用户代理支持的内容编码及内容编码的优先级顺序。 可一次性指定多种内容编码。
Accept-Encoding: gzip, deflate
常见的编码方式有:gzip、compress、deflate、identity。
# 2.4.Accept-Language
作用:用来告知服务器浏览器能够接收的语言 ,以及相对优先级。
Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3
上述值表示:优先请求中文版,其次是英文版;
# 2.5.Host
Host: www.hackr.jp
若服务器未设定主机名,Host
为空值即可。
# 2.6.If-Match
形如If--xxx
这种样式的请求首部字段,都可称为条件请求。服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。
上图表示:只有当If-Match
的字段值跟Etag
值匹配一致时,服务器才会接收请求。
# 2.7.If-Modified-Since
上图表示:如果在If-Modified-Since
字段指定的日期时间后,资源发生了更新,服务器会接收请求,此时返回状态码200
;否则会拒绝接收请求返回304
(因为资源都没更新过,不需要重新请求),与响应头Last-Modified
是一对;
# 2.8.If-None-Match
只有在 If-None-Match
的字段值与 ETag
值不一致时, 可处理该请求。 与 If-Match
首部字段的作用相反;
# 2.9.If-Range
首部字段 If-Range
属于附带条件之一。 它告知服务器若指定的 If-Range
字段值(ETag
值或者时间) 和请求资源的 ETag
值或时间相一致时, 则作为范围请求处理。 反之, 则返回全体资源。
下面我们思考一下不使用首部字段If-Range
发送请求的情况。 服务器端的资源如果更新, 那客户端持有资源中的一部分也会随之无效,当然,范围请求作为前提是无效的。这时,服务器会暂且以状态码 412:Precondition Failed
作为响应返回, 其目的是催促客户端再次发送请求。这样一来,与使用首部字段 If-Range
比起来,就需要花费两倍的功夫。
# 2.10.Referrer
作用:告诉服务器我是从哪个页面的链接过来的,服务器籍此可以获得一些信息用于处理;
Referer: http://www.hackr.jp/index.htm
# 2.11.User-Agent
作用:告诉HTTP服务器,客户端使用的操作系统和浏览器的名称和版本;
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/2010010
很多时候我们会通过该字段来判断浏览器类型,从而进行不同的兼容性设计。
# 3.响应首部字段
# 3.1.Age
首部字段 Age
能告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。
# 3.2.ETag
首部字段ETag
能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag
值。
另外, 当资源更新时,ETag
值也需要更新。生成 ETag
值时,并没有统一的算法规则,而仅仅是由服务器来分配。
与响应头If-None-Match
是一对;
# 3.3.Location
使用首部字段Location
可以将响应接收方引导至某个与请求 URI
位置不同的资源。 基本上,该字段会配合 3xx : Redirection
的响应, 提供重定向的URI
。
# 4.通用首部字段
# 4.1.Cache-Control
a.请求首部中Cache-Control的指令:
b.响应首部中Cache-Control的指令:
Cache-Control各指令详解:
**public指令:**客户端和代理服务器(
CDN
)可以缓存;**Private指令:**只有客户端可以缓存;
**no-store指令:**真正意义上的所有内容都不缓存;
**no-cache指令:**正确来说该指令还是会使用缓存,只不过使用前要确认其新鲜程度(协商缓存);
- **s-maxage = x指令 **:代理服务器请求源站缓存后的X秒内不再发出请求,只对
CDN
缓存(CDN
指的是拥有源服务器资源的多个分布式服务器)有效;
Cache-Control: s-maxage=604800 //(单位 : 秒)
此外,当使用 s-maxage
指令后,则直接忽略对 Expires
首部字段及max-age
指令的处理。 即优先级为:S-maxage
> Max-age
> Expires
- **Max-age = x指令:**请求缓存后的X秒内不再发起请求。
Cache-Control: max-age=604800 //(单位: 秒)
当客户端发送的请求中包含max-age
指令时: 如果判定指定的时间比缓存资源的缓存时间数值更大,那么客户端就接收缓存的资源。另外,当指定 max-age
值为 0
(指定时间更小),那么缓存服务器通常需要将请求转发给源服务器。
当服务器返回的响应中包含 max-age
指令时,缓存服务器将不对资源的有效性再作确认,而直接把 max-age
数值作为保存为缓存的资源的最长时效。
应用 HTTP/1.1
版本的缓存服务器遇到同时存在 Expires
首部字段的情况时,会优先处理 max-age
指令,而忽略掉 Expires
首部字段。
# 4.2.Connection
有两个作用:
- 控制不再转发给代理的首部字段:
如图中,Connection
的值为Upgrade
表示不将Upgrade
这个首部发给代理;
- 管理持久连接:
a.当Connection : close
时:
代表一个Request
完成后,客户端和服务器之间用于传输HTTP
数据的TCP
连接会关闭(四次挥手)。当客户端再次发送Request
,需要重新建立TCP
连接(三次握手)。
b.当Connection:Keep-Alive
时:
此时,当一个网页打开完成后(已经建立TCP连接),客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器,会继续使用这条已经建立的连接;
# 4.3.Via
使用首部字段Via是为了追踪客户端与服务器之间的请求和响应报文的传输路径:
# 5.实体首部字段
实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。
# 5.1.Content-Type
作用:说明报文内对象的媒体类型;
Content-Type: text/html; charset=UTF-8
# 5.2.Expires
首部字段 Expires
会将资源失效的日期告知客户端。缓存服务器(代理服务器)在接收到含有首部字段 Expires
的响应后,会以缓存来应答请求,在Expires
字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
源服务器不希望缓存服务器对资源缓存时, 最好在 Expires
字段内写入与首部字段 Date
相同的时间值。
但是,当首部字段Cache-Control
有指定 max-age
指令时,比起首部字段 Expires
,会优先处理 max-age
指令。
# 5.3.Last-Modified
首部字段 Last-Modified
指明资源最终修改的时间。 与请求头If-Modified-Since
是一对;
Last-Modeified: Wed, 23 May 2012 09:59:55 GMT
# 6.为 Cookie 服务的首部字段
Cookie
的工作机制是用户识别及状态管理。Web
网站为了管理用户的状态会通过 Web
浏览器,把一些数据临时写入用户的计算机内。接着当用户访问该Web
网站时,可通过通信方式取回之前发放的Cookie
;
调用 Cookie
时,由于可校验 Cookie
的有效期,以及发送方的域、路径、协议等信息,所以正规发布的 Cookie
内的数据不会因来自其他Web
站点和攻击者的攻击而泄露。
为 Cookie 服务的首部字段:
# 6.1.Set-Cookie字段
当服务器准备开始管理客户端的状态时,会事先告知各种信息。
Set-Cookie: status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT; path
2
**Set-Cookie
字段的属性 **
- expires 属性:
Cookie
的 expires
属性指定浏览器可发送 Cookie
的有效期。当省略 expires
属性时,其有效期仅限于维持浏览器会话(Session)
时间段内。 这通常限于浏览器应用程序被关闭之前。
另外,一旦 Cookie
从服务器端发送至客户端,服务器端就不存在可以显式删除 Cookie
的方法。但可通过覆盖已过期的 Cookie
,实现对客户端 Cookie
的实质性删除操作。
- domain 属性:
通过 Cookie
的domain
属性指定的域名可做到与结尾匹配一致。 比如,当指定 example.com
后,除 example.com
以外, www.example.com
或 www2.example.com
等都可以发送 Cookie
。
因此, 除了针对具体指定的多个域名发送 Cookie
之 外,不指定domain
属性显得更安全。
- secure 属性:
Cookie
的secure
属性用于限制 Web
页面仅在 HTTPS
安全连接时,才可以发送 Cookie
。
发送 Cookie
时,指定secure
属性的方法如下所示:
Set-Cookie: name=value; secure
以上例子仅当在https://www.example.com/(HTTPS)
安全连接的情况下才会进行Cookie
的回收。也就是说, 即使域名相同,http://www.example.com/(HTTP)
也不会发生 Cookie
回收行为。
当省略 secure
属性时,不论 HTTP
还是 HTTPS
,都会对 Cookie
进行回收。
- HttpOnly 属性:
Cookie
的 HttpOnly
属性是 Cookie
的扩展功能,它使 JavaScript
脚本无法获得 Cookie
。 其主要目的为防止跨站脚本攻击(Cross-sitescripting, XSS)
对Cookie
的信息窃取。
发送指定 HttpOnly
属性的Cookie
的方法如下所示。
Set-Cookie: name=value; HttpOnly
通过上述设置,通常从Web
页面内还可以对 Cookie
进行读取操作。但使用 JavaScript
的 document.cookie
就无法读取附加HttpOnly
属性后的Cookie
的内容了。 因此,也就无法在 XSS
中利用 JavaScript 劫Cookie
了。
# 6.2.Cookie字段
首部字段 Cookie
会告知服务器,当客户端想获得 HTTP
状态管理支持时, 就会在请求中包含从服务器接收到的 Cookie
。 接收到多个Cookie
时,同样可以以多个 Cookie
形式发送。
Cookie: status=enable
# 四、HTTP请求方法
HTTP/1.1 的常用方法 :
# 1.GET
GET
方法用来请求访问已被URI
识别的资源。指定的资源经服务器端解析后返回响应内容。
举例:
GET方法也可以用来提交表单和其他数据:
http://localhost/login.php?username=aa&password=1234
从上面的请求URL
中,很容易就能辨认出表单提交的内容。HTTP0.9
的时候只有GET
方法,所以GET
方法既能获取数据,也能提交数据,只不过提交的数据是拼接在URL
后的不能提交太多且不安全;提交大量数据时使用POST
方法。
# 2.POST
POST
方法功能与GET
方法类似,是GET
方法的延伸,主要用于向服务器提交数据量较大的用户表单数据;提交的数据放在请求报文的主体中,保证了提交数据的安全;这样就克服了
GET
方法提交的数据量太小和不能保密的缺点。POST
方法的主要目的并不是获取响应主体的内容;
# 3.PUT
PUT
方法用来传输文件。 就像FTP
协议的文件上传一样, 要求在请求报文的主体中包含文件内容, 然后保存到请求URI
指定的位置。PUT
方法和POST
很相似,最大的不同是:PUT
是幂等的,POST
是不幂等的。 即创建文件使用POST
更新文件使用PUT
;
幂等:幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同;
- 但是, 鉴于·
HTTP/1.1
的PUT
方法自身不带验证机制, 任何人都可以上传文件 , 存在安全性问题, 因此一般的Web
网站不使用该方法。
# 4.HEAD
HEAD
方法只获取响应报文首部,不返回报文主体部分。 用于确认URI
(超链接)的有效性及资源更新的日期时间等。 例如:
# 5.DELETE
DELETE
方法用来删除文件,是与PUT
相反的方法。DELETE
方法按请求URI
删除指定的资源。但是,
HTTP/1.1
的DELETE
方法本身和PUT
方法一样不带验证机制,所以一般的Web
网站也不使用DELETE
方法。(怎么可能让人随便rm -rf
) 举例:
# 6.OPTIONS
OPTIONS
方法用来查询针对请求URI
指定的资源支持的方法。
示例:
# 7.TRACE
客户端通过
TRACE
方法可以查询发送出去的请求是怎样被加工修改/ 篡改的。 这是因为, 请求想要连接到源目标服务器可能会通过代理中转,TRACE
方法就是用来确认连接过程中发生的一系列操作。但是,
TRACE
方法本来就不怎么常用, 再加上它容易引发XST
(Cross-Site Tracing
, 跨站追踪) 攻击, 通常就更不会用到了。发送请求时, 在
Max-Forwards
首部字段中填入数值, 每经过一个服务器端就将该数字减1
, 当数值刚好减到0
时, 就停止继续传输, 最后接收到请求的服务器端则返回状态码200 OK
的响应。
示例:
//请求
TRACE / HTTP/1.1
Host: hackr.jp
Max-Forwards: 2
响应:
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 1024
TRACE / HTTP/1.1
Host: hackr.jp
Max-Forwards: 2(返回响应包含请求内容)
2
3
4
5
6
7
8
9
10
11
12
13
# 8.CONNECT
CONNECT
方法要求在与代理服务器通信时建立隧道, 实现用隧道协议进行TCP
通信。 主要使用 SSL
(Secure Sockets Layer
, 安全套接层) 和TLS
(Transport Layer Security
, 传输层安全) 协议把通信内容加 密后经网络隧道传输。
//格式
CONNECT 代理服务器名:端口号 HTTP版本
//例子
//请求
CONNECT proxy.hackr.jp:8080 HTTP/1.1
Host: proxy.hackr.jp
//响应
HTTP/1.1 200 OK(之后进入网络隧道)
2
3
4
5
6
7
8
9
10
# 五、HTTP状态管理
Cookie和Session,实现了HTTP的状态管理,Cookie是在客户端的,Session是在服务器的。
# 1.Cookie
HTTP
是无状态协议(高效率,不记仇),它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。
假设要求登录认证的Web
页面本身无法进行状态的管理(不记录已登录的状态) ,那么每次跳转新页面不是要再次登录,就是要在每次请求报文中附加参数来管理登录状态。
保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了Cookie
技术。Cookie
技术通过在请求和响应报文中写入Cookie
信息来控制客户端的状态。
Cookie
实际上是一小段文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie
;- 客户端浏览器会把
Cookie
保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie
一同提交给服务器。服务器检查该Cookie
,以此来辨认用户状态。
在一个网站地址栏输入:
javascript:alert(document.cookie)
可以弹出该网站的Cookie
信息:
Cookie
会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie
的首部字段信息, 通知客户端保存Cookie
。当下次客户端再往该服务器发送请求时, 客户端会自动在请求报文中加入 Cookie
值后发送出去。
服务器端发现客户端发送过来的Cookie
后, 会去检查究竟是从哪一个客户端发来的连接请求, 然后对比服务器上的记录, 最后得到之前的状态信息。
# 第一次:没有 Cookie 信息状态下的请求
- 请求报文(没有 Cookie 信息的状态)
- **响应报文(服务器端生成 Cookie 信息) **
# 第二次:存有 Cookie 信息状态的请求
- **请求报文(自动发送保存着的 Cookie 信息) **
# 2.Session
Session
是另一种记录客户状态的机制,保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上;- 客户端浏览器再次访问时只需要从该
Session
中查找该客户的状态就可以了;
Cookie
和Session
非常相似,Cookie
相当于客户端持有的通行证,Session相当于服务器上的通行名册。
保存Session ID的方式
Cookie
URL
重写- 隐藏表单
Session的有效期
Session
超时失效:被动失效,如果超过规定时间没有再次访问服务器,Session
将失效;- 程序调用
HttpSession.invalidate()
:主动失效; - 服务器进程被停止;
# 3.Token
Token的引入
Token
是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token
便应运而生。
Token的定义
Token
是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token
便将此Token
返回给客户端,以后客户端只需带上这个Token
前来请求数据即可,无需再次带上用户名和密码。最简单的token
组成:uid
(用户唯一的身份标识)、time
(当前时间的时间戳)、sign
(签名,由token
的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token
请求服务器)。
使用Token的目的
Token
的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
Session管理及Cookie应用
步骤 1:客户端把用户
ID
和密码等登录信息放入报文的实体部分,通常是以POST
方法把请求发送给服务器。而这时,会使用HTTPS
通信来进行HTML
表单画面的显示和用户输入数据的发送。步骤 2:服务器会发放用以识别用户的
Session ID
。通过验证从客户端发送过来的登录信息进行身份认证, 然后把用户的认证状态与Session ID
绑定后记录在服务器端。向客户端返回响应时,会在首部字段
Set-Cookie
内写入SessionID
(如PHPSESSID=028a8c…
) 。为防止
Session ID
被第三方盗走,服务器端需要对其进行有效性管理;并且为减轻跨站脚本攻击(XSS)
造成的损失,建议事先在Cookie
内加上httponly
属性。步骤 3: 客户端接收到从服务器端发来的
Session ID
后,会将其作为Cookie
保存在本地。下次向服务器发送请求时,浏览器会自动发送Cookie
,所以Session ID
也随之发送到服务器。服务器端可通过验证接收到的Session ID
识别用户和其认证状态。
# 4.Cookie与Session的区别
- 存放位置不同:
Cookie
存放在客户端,Session
保存在服务器端; - 安全性(隐私策略)不同:
Cookie
存储在浏览器中,对客户端是可见的,客户端的一些程序可能会窥探或修改Cookie
的内容;而Session
存储在服务器端,对客户端来说是透明的;如果想要使用Cookie
需要对其进行加密; - 有效期上的不同:设置
Cookie
很大的过期时间,Cookie
就能被浏览器保存很长时间;而服务器会定期清理超时的Session ID
避免出现过大压力;但是Session
依赖于类似Session ID
这样的Cookie
,而Cookie
对Session ID
过期时间默许为-1
。所以只要关闭了浏览器,即一次会话结束后,该Session
就失效了; - 对服务器造成的压力不同:
Session
是保存在服务器端的,每个用户都产生一个Session
,假如并发访问的用户十分多,会产生十分多的Sssion
,耗费大量的内存;而Cookie
保存在客户端,不太占用服务器的资源;
# 六、HTTP协议的身份认证
BASIC
认证(基本认证)DIGEST
(摘要认证)SSL
客户端认证FormBase
认证(基于表单认证)
# 1.BASIC认证
BASIC 认证的认证步骤 :
步骤 1:当请求的资源需要
BASIC
认证时,服务器会随状态码401 Authorization Required
,返回带WWW-Authenticate
首部字段的响应。该字段内包含认证的方式(BASIC)
及Request-URI
安全域字符(realm)
。步骤 2: 接收到状态码
401
的客户端为了通过BASIC
认证, 需要将用户ID
及密码发送给服务器。 发送的字符串内容是由用户ID
和密码构成, 两者中间以冒号(:)
连接后,再经过Base64
编码处理。假设用户
ID
为guest
,密码是guest
,连接起来就会形成guest:guest
这样的字符串。 然后经过Base64
编码,最后的结果即是Z3Vlc3Q6Z3Vlc3Q=
。 把这串字符串写入首部字段Authorization
后, 发送请求。步骤 3: 接收到包含首部字段
Authorization
请求的服务器,会对认证信息的正确性进行验证。 如验证通过, 则返回一条包含Request-URI
资源的响应。
BASIC
认证虽然采用Base64
编码方式,但这不是加密处理。不需要任何附加信息即可对其解码。换言之,由于明文解码后就是用户 ID
和密码,在HTTP
等非加密通信的线路上进行 BASIC
认证的过程中,如果被人窃听,被盗的可能性极高。 因此并不常用。
# 2.DIGEST 认证
为弥补·BASIC
认证存在的弱点, 从 HTTP/1.1
起就有了 DIGEST
认证。DIGEST
认证同样使用质询 / 响应的方式
(challenge/response)
,但不会像 BASIC
认证那样直接发送明文密码。
所谓质询响应方式是指, 一开始一方会先发送认证要求给另一方, 接着使用从另一方那接收到的质询码计算生成响应码。 最后将响应码返回给对方进行认证的方式。
因为发送给对方的只是响应摘要及由质询码产生的计算结果,所以比起 BASIC
认证,密码泄露的可能性就降低了。
**DIGEST 认证的认证步骤: **
步骤 1:请求需认证的资源时,服务器会随着状态码
401:Authorization Required
,返 回带WWW-Authenticate
首部字段的响应。该字段内包含质问响应方式认证所需的临时质询码(随机数,nonce
) 。 首部字段WWW-Authenticate
内必须包含realm
和nonce
这两个字段的信息。客户端就是依靠向服务器回送这两个值进行认证的。nonce
是一种每次随返回的401
响应生成的任意随机字符串。该字符串通常推荐由Base64
编码的十六进制数的组成形式,但实际内容依赖服务器的具体实现。步骤 2: 接收到
401
状态码的客户端,返回的响应中包含DIGEST
认证必须的首部字段Authorization
信息。首部字段
Authorization
内必须包含username
、realm
、nonce
、uri
和response
的字段信息。其中,realm
和nonce
就是之前从服务器接收到的响应中的字段。步骤 3: 接收到包含首部字段
Authorization
请求的服务器,会确认认证信息的正确性。 认证通过后则返回包含Request-URI
资源的响应。并且这时会在首部字段Authentication-Info
写入一些认证成功的相关信息。
DIGEST
认证提供了高于BASIC
认证的安全等级,但是和 HTTPS
的客户端认证相比仍旧很弱。 DIGEST
认证提供防止密码被窃听的保护机制,但并不存在防止用户伪装的保护机制 。因此使用范围不大。
# 3.SSL 客户端认证
从使用用户ID
和密码的认证方式方面来讲,只要二者的内容正确即可认证是本人的行为。但如果用户 ID
和密码被盗,就很有可能第三者冒充。利用SSL
客户端认证则可以避免该情况的发生。
SSL
客户端认证是借由 HTTPS
的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来自已登录的客户端。
SSL 客户端认证的认证步骤 :
为达到SSL
客户端认证的目的 需要事先将客户端证书分发给客户端,且客户端必须安装此证书。
- 步骤 1:接收到需要认证资源的请求,服务器会发送
Certificate Request
报文,要求客户端提供客户端证书。 - 步骤 2:用户选择将发送的客户端证书后,客户端会把客户端证书信息以
Client Certificate
报文方式发送给服务器。
![image-20200318153348145](https://gitee.com/ahuntsun/BlogImgs/raw/master/HTTP/HTTP%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F/63.png)
- 步骤 3: 服务器验证客户端证书验证通过后方可领取证书内客户端的
165
公开密钥, 然后开始HTTPS
加密通信。
SSL 客户端认证采用双因素认证 :
在多数情况下,
SSL
客户端认证不会仅依靠证书完成认证,一般会和基于表单认证组合形成一种双因素认证(Two-factorauthentication)
来使用。换言之,第一个认证因素的
SSL
客户端证书用来认证客户端计算机,另一个认证因素的密码则用来确定这是用户本人的行为。使用
SSL
客户端认证需要用到客户端证书。而客户端证书需要支付一定费用才能使用。
# 4.基于表单认证
- 基于表单的认证方法并不是在
HTTP
协议中定义的; - 使用由
Web
应用程序各自实现基于表单的认证方式; - 通过
Cookie
和Session
的方式来保持用户的状态(具体见上);
也就是常见的登录:
输入已事先登录的用户ID
(通常是任意字符串或邮件地址) 和密码等登录信息后,发送给Web
应用程序,基于认证结果来决定认证是否成功。
# 七、HTTP的长连接与短连接
HTTP
协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP
请求就结束了;HTTP
的长连接和短连接本质上是TCP
的长连接和短连接;
# 1.短连接
完成一次通信之后,客户端主动断开TCP连接;
HTTP/1.0
中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP
操作,就建立一次连接(三次握手),结束就中断(四次挥手);
# 2.长连接
完成一次通信之后,客户端不主动断开 TCP
连接,而是复用该TCP
连接;
HTTP/1.1
起,默认使用长连接,用以保持连接特性。此时通用首部字段中的Connection
字段值为:Keep-Alive
;
长连接适用于频繁地传输数据的客户端和服务器,为了防止过多的TCP连接影响服务器性能,需要对长时间不用的连接进行释放;
# 八、代理、网关与隧道
HTTP
通信时,除客户端和服务器以外,还有一些用于通信数据转发的应用程序,例如代理、网关和隧道。它们可以配合服务器工作。
这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服务器发送的响应再转发给客户端。
# 1.代理
代理服务器:
代理是一种有转发功能的应用程序,它扮演了位于服务器和客户端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。
代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器。代理不改变请求URI
,会直接发送给前方持有资源的目标服务器。
持有资源实体的服务器被称为源服务器,从源服务器返回的响应经过代理服务器后再传给客户端。
每次通过代理服务器转发请求或响应时,会追加写入
Via
首部信息。
使用代理服务器的理由:
利用缓存技术(稍后讲解)减少网络带宽的流量,组织内部针对特定网站的访问控制(墙),以获取访问日志为主要目的,等等。
代理使用方法:
代理有多种使用方法,按两种基准分类。一种是是否使用缓存,另一种是是否会修改报文。
- **缓存代理 **
代理转发响应时,缓存代理(Caching Proxy
)会预先将资源的副本(缓存)保存在代理服务器上。当代理再次接收到对相同资源的请求时,就可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。
- **透明代理 **
转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理(Transparent Proxy
)。反之,对报文内容进行加工的代理被称为非透明代理。
# 2.网关
网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客户端可能都不会察觉,自己的通信目标是一个网关。
网关的工作机制和代理十分相似。但是Web
网关在一侧使用HTTP
协议,在另一侧使用另一种协议(比如FTP
、SMTP
)。
- (
HTTP/
)服务器端网关:通过HTTP
协议与客户端对话,通过其他协议与服务器通信; - (
/HTTP
)客户端网关:通过其他协议与客户端对话,通过HTTP
协议与服务器通信;
常见的网关类型:
(
HTTP/
*)服务器端Web
网关;(
HTTP/HTTPS
)服务器端安全网关:即客户端用HTTP
与网关通信,网关用HTTPS
与服务器通信;(
HTTPs/HTTP
)客户端安全加速器网关:即客户端用HTTPs
与网关通信,网关用HTTP
与服务器通信;也就是安全网关,将通过网关的不安全的
HTTP
转换为安全的HTTPS
;资源网关:客户端通过HTTP连接到应用程序的服务器,服务器并不回送文件,而是将请求通过网关API发送给运行在服务器上的应用程序,应用程序将请求资源会送给客户端。这样的客户端可能是一些网络摄像头,电子识别系统等;
利用网关能提高通信的安全性,因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。比如,网关可以连接数据库,使用SQL
语句查询数据。另外,在Web
购物网站上进行信用卡结算时,网关可以和信用卡结算系统联动。
# 3.隧道
隧道可按要求建立起一条与其他服务器的通信线路,届时使用SSL
等加密手段进行通信。隧道的目的是确保客户端能与服务器进行安全的通信。
隧道本身不会去解析HTTP
请求。也就是说,请求保持原样中转给之后的服务器。隧道会在通信双方断开连接时结束。
通过隧道的传输,可以和远距离的服务器安全通信。隧道本身是透明的,客户端不用在意隧道的存在。
# 九、HTTP缓存
缓存是指代理服务器或客户端本地磁盘内保存的资源副本。利用缓存可减少对源服务器的访问,因此也就节省了通信流量和通信时间。
缓存服务器是代理服务器的一种,并归类在缓存代理类型中。换句话说,当代理转发从服务器返回的响应时,代理服务器将会保存一份资源的副本。
缓存服务器的优势在于利用缓存可避免多次从源服务器转发资源。因此客户端可就近从缓存服务器上获取资源, 而源服务器也不必多次处理相同的请求了。
# 1.缓存的有效期限
即便缓存服务器内有缓存,也不能保证每次都会返回对同资源的请求。因为这关系到被缓存资源的有效性问题。 当遇上源服务器上的资源更新时,如果还是使用不变的缓存,那就会演变成返回更新前的“旧”资源了。
即使存在缓存,也会因为客户端的要求、缓存的有效期等因素,向源服务器确认资源的有效性。若判断缓存失效, 缓存服务器将会再次从源服务器上获取“新”资源。
# 2.客户端的缓存
缓存不仅可以存在于缓存服务器内,还可以存在客户端浏览器中。以Internet Explorer
程序为例,把客户端缓存称为临时网络文件(Temporary Internet File
);
浏览器缓存如果有效,就不必再向服务器请求相同的资源了,可以直接从本地磁盘内读取;
另外,和缓存服务器相同的一点是, 当判定缓存过期后, 会向源服务器确认资源的有效性。若判断浏览器缓存失效,浏览器会再次请求新资源。
# 十、HTTP缓存的工作方式(强制缓存与协商缓存)
# 1.场景一
让服务器与浏览器约定一个文件过期时间——Expires
在Expires
没有过期的情况下,客户端(浏览器)发出请求时,直接使用HTTP
本地缓存并返回状态码200
,这种HTTP
工作方式称为强制缓存;
# 2.场景二
让服务器与浏览器在约定文件过期时间Expires
的基础上,再加一个文件最新修改时间的对比——Last-Modified
与if-Modified-Since
- 情况1:如果
Expires
没有过期,浏览器直接使用HTTP
本地缓存,即采用强制缓存; - 情况2:如果
Expires
过期了,那么浏览器在请求服务器的时候,就带上了文件最新修改时间,这个字段是在请求头里面加上了If-Modified-Since
字段,其实该字段的值就是上次请求时服务器返回的Last-Modified
字段的值;服务器会把请求头里文件的最新修改时间If-Modified-Since
的值与服务器上的文件最新修改时间Last-Modified
的值进行比较:- 如果
If-Modified-Since
不等于Last-Modified
,说明浏览器缓存的资源(f.js
)发生改变,服务器就会去查找最新的f.js
,同时再次返回Expires
、f.js
、Last-Modified
,返回的状态码为200
; - 如果
If-Modified-Since
等于Last-Modified
,说明浏览器缓存的资源(f.js
)没有发生改变,浏览器可以继续使用HTTP
本地缓存,此时服务器返回状态码304
;这种方式称为协商缓存
- 如果
# 3.场景三
让服务器在过期时间Expires
+Last-Modified
的基础上,增加一个文件唯一标识Etag
与If-None-Match
配成一对使用;除此之外,Expires
不稳定,再加入一个Max-age
来加以替代(Max-age
优先级更高);
- 在60s内,浏览器不再向服务器发起请求,直接使用本地缓存这与
Expires
相似。 - 60s后:浏览器带上
If-Modified-Since
和If-None-Match
(也就是上次服务器返回的Etag
值)发起请求,服务器会对比If-None-Match
与服务器端的Etag
值,这时即使浏览器也提供了If-Modified-Since
也不会再与Last-Modified
进行对比,因为Etag
的优先级比Last-Modified
高(更精准);- 如果
If-None-Match
不等于Etag
,说明f.js
文件已被修改,服务器就会返回最新的f.js
和全新的Etag
与Max-age
(比如60
),当然也会顺便把Expires
与Last-Modified
返回(尽管没用);返回的状态码为200
; - 如果
If-None-Match
等于Etag
,说明f.js
文件没有被修改,这时服务器返回的状态码为304
,告诉浏览器继续使用原来的本地缓存。这种方式属于协商缓存;
- 如果
有了Last-Modified
为什么还要用Etag
呢?
你可能会觉得使用Last-Modified
已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag
呢?HTTP1.1
中Etag
的出现主要是为了解决几个Last-Modified
比较难解决的问题:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新
GET
; - 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说
1s
内修改了N
次),If-Modified-Since
能检查到的粒度是s
级的,这种修改无法判断(比如淘宝每ms
都会更新数据); - 某些服务器不能精确的得到文件的最后修改时间;
这时,利用Etag
能够更加准确的控制缓存,因为Etag
是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。 Last-Modified
与ETag
是可以一起使用的,服务器会优先验证ETag
,一致的情况下,才会继续比对Last-Modified
,最后才决定是否返回304
。
# 4.强制缓存与协商缓存
**强制缓存:**直接使用HTTP
本地缓存,此时服务器返回状态码200
;
协商缓存:向服务器确认HTTP
本地缓存的资源是否发生变化,没变化后再使用HTTP
本地缓存,此时服务器返回状态码304
;资源发生变化直接返回最新资源,状态码为200
;可以这样理解凡是返回304
状态码,都属于协商缓存;
强缓存和协商缓存的区别:
缓存 | 获取资源形式 | 状态码 | 发送请求到服务器 |
---|---|---|---|
强缓存 | 从缓存读取 | 200(From Cache) | 否,直接从缓存读取 |
协商缓存 | 从缓存读取 | 304(Not Modified) | 是,通过服务器告知浏览器缓存是否可用 |
请求头Cache-Control
的值为no - cache时表示浏览器会先向服务器确认缓存的新鲜度,再决定是否使用缓存,属于协商缓存。
# 5.缓存改进方案
上述的缓存方案存在一个问题:当Expires
或Max-age
没有过期时,浏览器无法主动确认本地缓存是否发生变化;
# 5.1.md5/hash缓存
通过不缓存html
,为静态文件添加MD5
或者hash
标识,解决浏览器无法跳过缓存过期时间主动感知文件变化的问题;具体过程为:第一次加载静态文件时,某位置指定加载f-hash1.js
,第二次加载静态文件时同一个位置指定加载f-hash2.js
,此时浏览器就会重新向服务器请求数据了;
# 5.2.CDN缓存(最常用)
CDN
是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率;
比如可以把CDN
理解为各个城市的快递分发站点,源服务器看作快递总仓库;
CDN缓存工作方式:
- 第一次缓存:
- 后续请求:
CDN
节点会代替服务器处理浏览器的请求,会有几种情况:
- 情况一:
CDN
节点缓存的文件还没过期,于是返回304
给浏览器,浏览器此次请求被拦截(协商缓存); - 情况二:
CDN
节点发现自己缓存的文件过期了,为了保险起见自己发送请求给服务器成功拿回了最新的数据,然后再交还给浏览器;
可以发现,CDN
缓存问题与HTTP
缓存是一样的。只不过CDN
缓存不过期浏览器始终被拦截,无法拿到最新的文件;另外的不同点在于CDN
相当于一个平台可以手动登录更新缓存,这也就变相解决了不能控制HTTP
本地缓存的问题。
# 6.浏览器操作对HTTP缓存的影响
用户操作 | Expires/Cache-Control | Last-Modified/Etag |
---|---|---|
地址栏回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
新开窗口 | 有效 | 有效 |
前进、后退 | 有效 | 有效 |
F5刷新 | 无效 | 有效 |
Ctrl + F5刷新 | 无效 | 无效 |
由上表可知:对于Last-Modified
和Etag
字段来说,只有在进行Ctrl + F5
强制刷新时,这两个字段对缓存是否有效的控制才会失效。即强制刷新后,浏览器不会使用本地缓存,而是直接向服务器发起请求。
# 十一、内容协商机制
指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为合适的资源。内容协商会以响应资源的语言,字符集,编码方式等作为判断的基准。
有三种方式:
- 客户端驱动
由客户端发起请求,服务器发送可选项列表,客户端作出选择后在发送第二次请求;
- 服务器驱动
服务器检查客户端的请求头部集并决定提供哪个版本的页面;
- 透明协商
某个中间设备(通常是缓存代理)代表客户端进行协商;
# 1.服务器驱动
服务器驱动内容协商:请求首部集;
- Accept:告知服务器发送何种媒体类型;
- Accept-Language:告知服务器发送何种语言;
- Accept-Charset:告知服务器发送何种字符集;
- Accept-Encoding:告知服务器采用何种编码;
服务器驱动内容协商:实体首部集;
- Content-Type
- Content-Language
- Content-Type
- Content-Encoding
与请求首部集一一对应;
# 十二、断点续传和多线程下载
HTTP
是通过在Header
里两个参数实现的,客户端发出请求时对应的是Range
,服务器端响应时对应的是Content-Range
,如果续存成功返回206
,如果文件有变动返回200
和新文件的内容;
# 1.Range
用于请求头中,指定第一个字节的位置和最后一个字节的位置,格式为:
//格式(左开右闭)
Range:(unit = first byte pos) - [last byte pos]
//示例
Range: bytes=5001-10000
2
3
4
5
接收到附带 Range
首部字段请求的服务器,会在处理请求之后返回状态码为 206 Partial Content
的响应。 无法处理该范围请求时,则会返回状态码 200 OK
的响应及全部资源。
断点续传过程
1
.客户端下载一个1024K
的文件,已经下载了其中的512K
。2
.网络中断,客户端请求续传,因此需要在HTTP
头中申明本次需要续传的片段:Range:bytes
=512000~
这个头通知服务器端从文件的512K
位置开始传输文件;3
.服务器收到断点续传请求,从文件的512K
开始传输,并且在HTTP
头中增加:Content-Range:bytes 512000-/1024000
1并且此时服务端返回的
HTTP
状态码应该是206 Partial Content
,而不是200
;
# 十三、HTTPS
HTTPS
使用的是TSL
协议(SSL
是TSL
协议的一种);
# 1.HTTPS的功能
- 内容加密
- 非对称密钥加密:传输公钥时可能被截获并掉包,解决方案:使用第三方机构颁发的证书加密公钥(根据服务器地址等多个信息生成,无法被第三方伪造),浏览器收到后使用证书机构颁发的公钥进行解密(前提是浏览器要信任同一个证书颁发机构)解密结果与用证书生成的规则再生成一个签名对比一致就是真证书;
- 对称密钥加密:中间人随意截获
- 身份认证
- 数字证书
- 数据完整性
# 2.HTTPS的使用成本
HTTPS
是一个大趋势
证书费用以及更新维护
- 证书现在不贵,也有免费的;
HTTPS降低用户访问速度
- 经过合理的优化(比如
SPDY
)和部署甚至可以比HTTP1.0
快,不过这也是成本之一就是了;
- 经过合理的优化(比如
消耗CPU资源,需要增加大量机器
- 需要多次计算
# 3.HTTPS对性能的影响
- 协议交互所增加的网络RTP(往返时延)
- 加解密相关计算的耗时
网络耗时: HTTP
只需要通过TCP
的三次握手就能建立HTTP
连接:
而HTTPS
除了TCP
的三次握手外,甚至还需要耗费额外的7
个RTP
进行验证
关于302
自动跳转,这是因为,比如访问百度,我们输入网址全称而是输入baidu.com
,所以会自动跳转至HTTPS
,这本身也需要耗时;
并且跳转后,URI
不一样了,浏览器要与服务器重新通过三次握手建立TCP
连接;
之后还要进行TLS
协商,比如密钥交换算法,对称加密算法,内容一致性校验算法,证书签名算法等等;浏览器获取到证书后,也需要校验证书的有效性,比如证书是否过期,是否撤销等等;
接着,浏览器首先获取证书里的CA
域名如果该CA
域名没有命中缓存,浏览器需要解析域名的DNS
,这个DNS
解析至少耗费一个RTP
;
DNS
解析到IP
之后就要完成三次握手,建立CA
站点的TCP
连接,这又耗费一个RTP
;
再接着浏览器发送OCSP
请求,获取响应耗费一个RTP
;
关于
OCSP
:在线证书状态协议,它是维护服务器和其他网络资源安全性的两种普遍模式之一,另外一个叫做CRL
证书注销列表;当用户试图访问一个服务器的时候,在线证书状态协议发送一个对于证书状态信息的请求,服务器会回复一个有效、过期、未知的响应;协议规定了服务器和客户端应用程序通信的语法;在线证书协议给了用户到期证书一个宽限期,这样用户就可以在更新证书前的一段时间继续访问服务器,所以这里就需要发起一个对于证书状态的请求,也需要消耗一个RTP
最后就是TLS
完全握手阶段2
,这个阶段主要进行密钥协商,耗时一个RTP
;随后进行应用层的TCP
数据通信。
计算耗时
- 浏览器计算耗时;
- 服务器计算耗时;
# 4.HTTPS常见问题
HTTPS
需要安装证书大型网站比如百度,从
HTTP
升级为HTTPS
比较困难(不能因为升级而降低用户体验这样就本末倒置了)HTTPS
并不能解决所有安全问题(比如XSS
攻击,木马等),只是能更加安全的传输数据
# 5.影响HTTP网络请求的因素
- 带宽
- 延迟
- 一条连接上只可发送一个请求;
- 请求只能从客户端开始,客户端不可以接收除响应以外的指令;
- 请求/响应头部不经压缩就发送,每次互相发送相同的头部造成的浪费很多;
- 非强制压缩发送;
# 十四、WebSocket
可以理解为WebSocket
是为了让HTTP
支持长连接而打的一个大补丁;
WebSocket
是一个持久化的HTTP
,而HTTP
本身是非持久化的如下图所示:(虽然有Keep-Alive
)
# 1.WebSocket的握手
请求:
响应:
Upgrade
:表示升级为WebSocket
# 2.WebSocket的作用
HTTP的瓶颈
请求只能从客户端发起,客户端不可以接收除了响应之外的指令;当客户端需要监听服务器上的内容时,在HTTP中有一些优化处理方式,常用的用:Ajax轮询,Long Poll
- Ajax轮询
原理为,客户端每隔几秒就发送一次请求,询问服务器到底有没有新消息;若有服务器返回新消息,没有就返回提示信息,如此循环:
- Long Poll长轮询
与Ajax轮询原理相似,客户端先发出请求,直到服务器上有新数据返回之前,都不再发送请求,如此循环:
缺陷:两种方式都非常消耗资源,Ajax轮询需要服务器有很快地处理速度;Long Poll需要服务器有很大容量;
- 异常情况
WebSocket解决上上述问题
首先使用HTTP
协议通知服务器升级到WebSocket
协议,随后在WebSocket
协议中,服务器端是可以主动推送数据给客户端的,详细过程:
WebSocket的特点
相比于HTTP
的长连接,WebSocket
具有以下特点
真正的全双工方式:服务器可以主动推送,
HTTP
的长连接仍然是客户端主动发起请求的;减少通信量:不需要重复传输
HTTP Header
等信息;持久性连接:只要进行一次
HTTP
连接,两者就能创建持久的WebSocket
连接;
# 十五、SPDY
SPDY是HTTP
的增强,在向下兼容的情况下,在TLS
层上新增一层会话层SPDY
,使用这个会话层来实现SPDY
协议,也就是说现有的服务格式均不用改变吗;SPDY是对HTTP
的一个更好的实现和支持;
# 1.HTTP的缺陷
- **单路连接,请求低效:**最大的弊端所在:每个
TCP
连接只能对应一个HTTP
请求;也就是每个HTTP
请求只能请求一个资源;浏览器只能通过建立多个连接来解决低效问题。 - **对请求严格的先进先出:**如果中间的某个请求处理时间比较长的话,就会阻塞后面的请求;
- **只允许由客户端主动发起请求:**客户端只能接收服务器发出的响应,服务器无法主动推送信息;
- HTTP的头部冗余:
HTTP
的头在一个会话里是反复传送的,中间的冗余信息比如:User-Agent
、Host
的等不需要重复发送的信息也在不断地重复发送,浪费带宽和资源;
# 2.SPDY的改进
所以基于HTTP
的上述缺陷,SPDY进行了以下改进:
- 多路复用请求优化:
SPDY
规定在一个SPDY
连接内可以有无限个并行的请求,即多个并发的请求共用一个TCP
会话;只需要建立一个TCP
连接就可以传送网页上的所有资源;减少了时延,节省了资源,把TCP
连接的效率发挥到了最高; - 可以设置请求的优先级:不必遵守
HTTP
那样的先进先出,而是可以优先传输CSS
这些更重要的资源,然后再传输网站图标这样不太重要的资源。 - 支持服务器推送功能:可以实现预加载,比如浏览器请求了
style.css
,服务器就会主动把style.js
推送给浏览器。这样浏览器请求style.js
是就可以直接使用本地缓存了;这 与WebSocket
不同在于,这是资源的主动推送; - SPDY压缩了HTTP头:舍弃了不必要的
Header
头,可以节省多余数据造成的等待时间,占据的带宽等; - 强制使用SSL传输协议:客户端全部的请求都要经过
SSL
加密后才能传输;
直观的影响
对于前端工程师而言,页面优化永远是一个课题。有了SPDY
的请求优化,可以将请求顺序重新编排,这样很大程度上缓解了页面加载时图片请求带来的影响;减少了HTTP
的请求;
# 十六、HTTP2.0
上面所讲的SPDY
后来被谷歌放弃了,转而成为了HTTP2.0
的前身,基于SPDY
的核心改造升级开发出了HTTP2.0
。所以两者有比较多相似的地方:
# 1.HTTP2.0性能增强的核心:二进制分帧
在HTTPS
的基础上新增了二进制分帧层:Binary Framing
,在该层上HTTP2.0
会将所有的传输信息分割成更小的消息和帧,并对其采用二进制格式的编码;
如下图所示:
- 请求头信息被封装进了
HEADERS frame
中,请求报文主体被封装进了DATA frame
中; HTTP2.0
的通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息由一个或多个帧组成。这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。
# 2.HTTP2.0首部压缩
HTTP2.0
在服务器端和客户端使用首部表来跟踪和存储之前发送的键值对,对于相同的数据不再通过每次请求和响应发送,通讯期间几乎不会改变通用的键值对,比如:Host
、User-agent
等只需要发送一次;如果这个请求不包含首部,那么首部的开销就变为0
字节了,此时首部都自动使用之前发送请求的首部;
如下图所示,Request # 2
中只需要在HEADERS frame
里发送:path
这个变化的头部即可,其他头部信息直接沿用Request #1
的请求头;或者说新增或变化的头部信息会被追加到新的首部表中,如图中的Request #2
。它在HTTP2.0
的连接存续期内是始终存在的,由客户端和服务器端共同地渐进地更新;
# 3.HTTP2.0多路复用
多路复用这也是继承于SPDY
协议的,HTTP2.0
所有的通信都在一个TCP
连接上完成。HTTP2.0
把HTTP
通信的基本单位缩小为一个一个的帧,这些帧对应于逻辑流里面的信息,并行的在同一个TCP
连接上双向交换;
TCP
连接性能的关键在于低延迟。大多数HTTP
连接的时间都很短,而且是突发性的,而TCP
只在长时间传输连接,传输大块数据的时候效率是最高的;HTTP2.0
通过让所有的数据流公用一个TCP
连接可以更有效地使用TCP
连接,让高带宽也能真正地服务于HTTP
的性能提升上。
但链接多资源的优势
可以减少服务器建立大量链接的压力,内存占用更少,连接吞吐量变大了。
由于
TCP
连接减少而使网络拥塞状况得以改观;慢启动时间减少,拥塞和丢包恢复速度更快;
也就是说,资源合并减少请求的方式,对于HTTP2.0
来说是没有效果,只会开发者无用的工作量而已。所以当HTTP2.0
普及之后,像雪碧图呀,文件合并等就没有多大意义了。
# 4.并行双向字节流的请求和响应
简单点说就是可以乱序发送,在HTTP2.0
上客户端和服务器可以把HTTP
数据的消息分解为互不依赖的数据帧,然后乱序发送,最后在接收端把这些乱序帧重新组合起来。如图所示,同一个连接有多个不同方向的数据流在传输,所以客户端可以一边乱序地发送数据帧,也可以接收服务器的响应;服务器端也是如此都是双向的。
所以:把HTTP
消息分解为独立的帧交错发送,然后在另一端重新组装是HTTP2.0
一项很重要的增强;
这一特性会发生连锁反应带来巨大的性能提升:
- 并行交错地发送请求,请求之间互不影响;
- 并行交错地发送响应,响应之间互不干扰;
- 只是用一个连接即可并行发送多个请求和响应;
- 消除不必要的延迟,减少页面加载的时间;
# 5.请求优先级
HTTP2.0
的这一特性也是继承于SPDY
,服务器处理不同的流采取不同的优先策略;
- 高优先级的流都应该优先发送;
- 优先级不是绝对的;
- 不同优先级混合也是必须的;
# 6.服务器推送
毕竟HTTP2.0
的核心是从SPDY
的基础上衍生而来的;服务器可以对客户端的一个请求发送多个响应,即除了对最初请求的响应之外服务器还可以额外向服务器推送其他资源,而无需客户端明确请求;如图所示:客户端请求了html
文件,服务器就会把js
与css
文件推送给客户端:
# 十七、WebDAV协议
WebDAV
(Web-based Distributed Authoring and Versioning
,基于万维网的分布式创作和版本控制)是一个可对 Web
服务器上的内容直接进行文件复制、编辑等操作的分布式文件系统(可在线修改文件的网盘)。
除了创建、删除文件等基本功能,它还具备文件创建者管理、文件编辑过程中禁止其他用户内容覆盖的加锁功能, 以及对文件内容修改的版本控制功能。
使用 HTTP/1.1
的 PUT
方法和 DELETE
方法, 就可以对 Web
服务器上的文件进行创建和删除操作。 可是出于安全性及便捷性等考虑,一般不使用。
# 1.WebDAV 内新增的方法及状态码
WebDAV
为实现远程文件管理,向 HTTP/1.1
中追加了以下这些方法。
方法 | 用途 |
---|---|
PROPFIND | 获取属性 |
PROPPATCH | 修改属性 |
MKCOL | 创建集合 |
COPY | 复制资源及属性 |
MOVE | 移动资源 |
LOCK | 资源加锁 |
UNLOCK | 资源解锁 |
新增状态码:
状态码 | 含义 |
---|---|
102 Processing | 可正常处理请求,但目前是处理中状态 |
207 Multi-Status | 存在多种状态 |
422 UnprocessibleEntity | 格式正确,内容有误 |
423 Locked | 资源已被加锁 |
424 FailedDependency | 处理与某请求关联的请求失败,因此不再维持依赖关系 |
507 InsufficientStorage | 保存空间不足 |
**WebDAV 的请求实例 **
下面是使用 PROPFIND
方法对http://www.example.com/file
发起获取属性的请求 :
PROPFIND /file HTTP/1.1
Host: www.example.com
Content-Type: application/xml; charset="utf-8"
Content-Length: 219
//...请求主体
2
3
4
5
6
**WebDAV 的响应实例 **
下面是针对之前的 PROPFIND
方法, 返回http://www.example.com/file
的属性的响应。
HTTP/1.1 207 Multi-Status
Content-Type: application/xml; charset="utf-8"
Content-Length: 831
//...响应主体
2
3
4
5
不过可以使用FTP
替代它;
# 十八、HTTP3.0
# 1.HTTP2.0的问题
- 队头阻塞:由于只建立一个
TCP
连接,一旦出现某次传输出现丢包,就要等待重传,严重阻碍了其他数据的传输; - 建立连接的握手延迟大:
HTTPS
和HTTP2.0
除了建立TCP
握手之外,还要建立TSL
安全传输,这就出现了两次握手延迟;对于短连接来说,影响无法被移除,这些都是TCP
的历史遗留问题;
# 2.QUIC的特性
- 0 RTP:两层意思,建立
UDP
连接和建立TSL
安全连接大多数情况只需要0 RTP
;
- 没有队头阻塞的多路复用
当TCP
连接中传输的数据流stream2
中出现丢包时,在发送端没有重传丢失的包之前跟在stream2
后面的stream3/4
就被阻塞住了;
然而UDP
连接中,数据流彼此间没有依赖关系,即使stream2
出现丢包,也不影响其他stream
数据的传输;
- 前向纠错(
Front Error Collection
)
每个数据包除了它本身的数据之外,还包括了部分其他包的内容,因此少量的丢包可以通过其他包的冗余数据直接组装,而无需重传;这种方法虽然牺牲了每个数据包可发送数据的上限,但是减少了因为丢包导致的数据重传(更浪费时间);如果丢失的包过多,就只能通过重传来解决。
QUIC融合了UDP
协议的速度性能和TCP
的安全和可靠,大大优化了互联网传输数据的体验。
# 3.HTTP协议总结
HTTP1.0/1.1
:有连接无法复用、队头阻塞、协议开销大和安全因素等多个缺点;HTTP2.0
:通过多路复用、二进制流、头部压缩等技术极大地提升了性能,但是还是存在问题;HTTP3.0
:QUIC
是基于UDP
实现的,是HTTP3.0
的底层支持协议。该协议基于UDP
又吸收了TCP
的精华,实现了既快又可靠的连接;
# 十九、Web安全
# 1.概述
日常生活中的”安全“
- 为什么登录的时候经常要求我们输入一个验证码?
- 在一个网站上长时间没有操作,为什么
Session
会失效?
# 1.1.WASC的定义
全程Web Application Security Consortium
:是一个由安全专家、行业顾问和诸多组织的代表组成的国际团体,负责为WWW
(万维网)制定广为人知的应用安全标准。
# 1.2.六类Web应用安全威胁
名称 | 中文名 | 作用 |
---|---|---|
Authentication | 验证 | 用来确认某用户、服务或是应用身份的攻击手段 |
Authorization | 授权 | 用来决定是否某用户、服务或是应用具有执行请求动作必要权限的攻击手段 |
Client-Side-Attacks | 客户侧攻击 | 用来扰乱或是探测Web 站点用户的攻击手段 |
Command Execution | 命令执行 | 在Web 站点上执行远程命令的攻击手段(比如SQL 注入) |
Information Disclosure | 信息泄露 | 用来获取Web 站点具体系统信息的攻击手段 |
Logical Attacks | 逻辑性攻击 | 用来扰乱或是探测Web 应用逻辑流程的攻击手段 |
# 1.3.OWASP的定义
全称Open Web Application Security Project
,该组织致力于发现和解决不安全Web
应用的根本原因;它们最重要的项目之一是Web应用的十大安全隐患
总结了目前Web
应用最常受到的十种攻击手段,并且按照攻击发生的概率进行了排序(以下为2017
年的数据):
排名 | 漏洞种类 | 详情 |
---|---|---|
A1 | 注入 | 将不受信任的数据作为命令或查询的一部分发送到解析器时,会产生注入:SQL 注入、NoSQL 注入、OS 注入和LDAP 注入缺陷。 |
A2 | 失效的身份认证 | 通过错误的使用应用程序的身份认证和会话管理功能,攻击者能够破译密码、密钥或会话令牌 |
A3 | 敏感数据泄露 | 许多Web 程序和API 都无法正确保护敏感数据,攻击者可通过窃取或修改未加密的数据来实施信用卡诈骗、身份盗窃等犯罪行为 |
A4 | XML外部实体(XXE) | 许多较早的或配置错误的XML 处理器评估的XML 文件中的外部实体引用。攻击者可利用外部实体窃取内部文件、执行远程代码 |
A5 | 失效的访问控制 | 未对通过身份验证的用户实施恰当的访问控制 |
A6 | 安全配置错误 | 安全配置错误是最常见的安全问题,这通常是由于不安全的默认配置、不完整的临时配置、开源云错误等造成 |
A7 | 跨站脚本(XSS) | XSS 让攻击者能够在受害者的浏览器中执行脚本,并劫持用户会话、破坏网站或将用于重定向到恶意站点 |
A8 | 不完全的反序列化 | 不安全的反序列化会导致远程代码执行 |
A9 | 使用含有已知漏洞的组件 | 组件如库、框架和其他软件模块拥有和应用程序相同的权限 |
A10 | 不足的日志记录和监控 | 不足的日志记录和监控,以及事件响应缺失或无效的集成,使攻击者能够进一步攻击系统、保持持续性、篡改、提取或销毁数据 |
# 2.验证机制
验证机制是Web
应用程序中最简单的一种安全机制,也是防御恶意攻击的核心机制;
# 2.1.典型的身份验证模式
验证技术
- 基于HTML表单的验证
- 多元机制,如组合密码;
- 客户端
SSL
证书
弱密码
许多Web
应用程序没有或很少对用户密码强度进行控制;
暴力破解
登录功能的公开性会诱使攻击者试图猜测用户名和密码,从而获得访问应用程序的权力;
暴力破解-安全措施
验证码技术:最常见和有效的应对方式,需要注意几个问题:
验证码是否真实有用
验证码的复杂度:从最开始的数字,到数字字母组合,再到谷歌奇形怪状的字母;
应对当前的”打码“事业盛行:使用专门平台的”打码“服务器进行破解;对此出现了点击型的验证码、滑动型的验证码、问答型的验证码等更高级的验证码;
Cookie和会话检测:有些应用程序会设置一个Cookie,如
failedlogin = 0
;尝试登录失败,递增该值,达到某个上限,检测到这个值并拒绝再次处理登录;- 这样也不安全,只要客户端的
Cookie
在到达服务器端前被截获,就能被篡改;
- 这样也不安全,只要客户端的
双因子认证:双因子认证的核心是综合
What you know
(个人密码)和What you have
(手机)来达到双重认证效果;(较安全常用)
# 3.会话管理机制
绝大多数
Web
应用程序中,会话管理机制是一个基本的安全组件。会话管理机制在应用程序执行登录功能时尤为重要,因为:它可以在用户通过请求提交它们的证书后,持续向应用程序保证任何特定用户身份的真实性;由于会话管理机制所发挥的关键作用,它们就成为了针对应用程序的恶意攻击的主要目标;
若攻击者能够破坏应用程序的会话管理,他就能轻易避开其实施的验证机制,不需要用户证书即可伪装成其他应用程序用户。
# 3.1.会话管理存在的漏洞
会话令牌生成漏洞:比如采用常见的算法生成,容易被人猜出算法名称进行反编译破解;
令牌可预测:比如隐含序列,事件依赖;
会话终止攻击:会话结束后,Cookie没有真正意义上被删除,下次验证还有效;
会话劫持攻击:比如网络嗅探、
XSS
攻击等方式获取用户的会话令牌;
# 3.2.会话管理漏洞的防御
令牌传输安全
- 令牌只能通过HTTPS传送;
- 如果使用
HTTP cookie
传送令牌(大多数情况下)应该将Cookie
字段标记为Secure
,以防止用户浏览器通过HTTP
传送它们;
增加软硬会话过期
- 软会话过期:它指的是用户在一定的时间内与应用系统没有交互,则会话过期也就是我们常说的Session失效;
- 硬会话过期:它指的是用户登录到系统中经过一定的时间后,不管用户做什么,该会话都会过期(网吧上网时间到了,强制下机);
# 二十、常见的网络攻击
# 1.SQL注入攻击
# 1.1.SQL注入原理
- 几乎每个
Web
应用都需要使用数据库来保存操作所需要的各种信息; - 所以
Web
程序是经常会建立用户提交数据的SQL
语句; - 最严重的情况下,攻击者可利用
SQL
注入,读取甚至修改数据库中保存的所有数据; - 用户可以提交一段数据库查询代码,根据程序返回结果,获得某些他想得知的数据;
这就是所谓的SQL Injection,即SQL
注入;比如:
帐户名中输入的‘or’1 = 1
会被识别为SQL
操作指令;
# 1.2.SQL注入危害
- 探知数据库的具体结构,为进一步攻击准备;
- 泄露数据,尤其是机密信息、账户信息等;
- 取得更高权限,用来修改数据甚至是内部结构;
# 1.3.SQL注入防御
参数化查询
参数化查询是对
SQL
注入根本性的防御策略,也叫做预处理语句,在建立一个包含用户输入的SQL
语句时分为两步:- 指定查询结构,用户输入预留占位符;
- 指定占位符内容;
比如使用问号
?
当作占位符,这样即使输入了SQL
语句这样也不会被认为是数据SQL
的一部分,而是用户输入内容。
字符串过滤
使用正则表达式过滤传入的参数
# 2.跨域脚本攻击(XSS)
跨站脚本攻击(Cross Site Scripting
),XSS
(CSS
已被占用所以叫XSS
)是一种经常出现在Web
应用中的计算机安全漏洞;
它允许Web
用户恶意地将代码植入到提供给其他用户使用的页面中,其他用户在观看网页时,恶意脚本就会执行;
# 2.1.XSS攻击原理
- 这类攻击通常通过注入
HTML
或JS
等脚本发动攻击; - 攻击成功后,攻击者可以得到私密网页内容和
Cookie
等; - 最近几年
XSS
攻击已成为最流行的攻击方式;
# 2.2.XSS攻击危害
- 盗取各类用户账号:如机器登录账号、用户网银账号、各类管理员账号;
- 控制数据:包括读取、篡改、添加、删除企业敏感数据的能力;
- 盗窃企业重要的具有商业价值的资料;
- 非法转账;
- 强制发送网站挂木马;
- 控制受害者机器,让该用户成为"肉机",向其他网站发起攻击;
# 2.3.XSS攻击真实案例
Myspace XSS攻击事件
- 2005年,一名叫做
samy
的用户发现了Myspace
(社交网站)的XSS
漏洞,他在用户资料页面插入了一些javascript
脚本; - 如果一个用户查看了他的用户资料,这段脚本就会被执行;
- 脚本包括两方面:一是把
Samy
加为好友,二是将上面说的脚本复制到受害者自己的用户资料页面中; - 于是,所有查看受害者用户资料的用户也会成为受害者;
- 一个基于存储式
XSS
攻击的蠕虫迅速扩散,几个小时内,Samy
收到了近百万个好友的申请; - 为此,
Myspace
被迫关站,修复反XSS
过滤机制并且从所有用户的资料中删除含有恶意脚本的内容;
# 2.4.XSS分类
针对XSS
的攻击方式不同,可以把XSS
分为如下三大类:
- 反射式XSS
- 存储式XSS
- 基于DOM的XSS
# 反射式XSS
也称为非永久性XSS,目前最流行的XSS
攻击;它出现在服务器直接服务器直接使用客户端提交的数据,如URL
的数据、HTML
表单中提交的数据,并且没有对数据进行无害化处理;如果提交的数据中含有HTML
控制字符而没有被正确处理,那么一个简单的XSS
攻击就会发生。
典型的反射式攻击方式可通过一个邮件或中间网站,诱饵是一个看起来可信任的站点的链接,其中包含XSS
攻击脚本,比如社交群中常发的游戏活动、赌博、美女链接等。如果信任的网站没有正确处理这个脚本,用户点击后就会导致浏览器执行含有恶意攻击的脚本。
# 存储式XSS
也称为永久性XSS,危害更大。攻击将攻击脚本上传到Web
服务器上,使得所有访问该页面的用户都面临信息泄露的可能,其中也包括了Web
服务器的管理员;
存储式XSS
多发生在最终显示给其他用户的位置包含:
- 个人信息字段,如姓名、地址、电子邮件、电话等;
- 文档、上传文件及其他数据的名称;
- 提交给应用程序管理员的反馈或问题;
- 向其他应用程序用户传送的消息、注释、问题等;
- 在用户之间共享的上传文件内容;
典型的存储式XSS攻击过程
- 我拥有一个
Web
站点,该站点允许用户发布信息/浏览已发布信息; - 你注意到我的站点具有存储式的
XSS
漏洞; - 于是你发布一个热点信息,利用该漏洞获取用户信息,吸引其他用户纷纷阅读;
- 任何其他人浏览该信息,其绘画
Cookies
或其他信息都会被你盗走;
# 基于DOM的XSS攻击
反射式XSS
攻击和存储式XSS
攻击都是通过服务器提取用户提交的数据,并且以不安全的方式将其返回给用户;基于DOM
的攻击仅仅通过JavaScript
的方式执行;
也就是说这种攻击常发生在应用程序每次返回相同的静态页面(HTML
文件),并通过客户端的js
文件动态生成信息,并不会与服务器交互获取该js
文件的时候;
# 2.5.XSS攻击载荷
会话令牌
XSS
攻击对普遍的方式;- 截取一名受害者的会话令牌(
Token
),劫持他的会话,进而作为受害者的身份来使用应用程序,执行任意操作并占有该用户的账号;
虚拟置换
这种攻击需要在一个
Web
应用程序页面注入恶意数据,从而向应用程序的用户传送误导性信息;包括简单的向站点注入
HTML
,或者使用脚本注入精心设计的内容;比如在淘宝的搜索结果页面中注入一个链接,受害者点击后跳转到一个和淘宝很像的钓鱼网页,登录时帐户信息就被泄露了;
攻击者实际上没有修改保存在服务器上的内容,而是利用程序处理并显示用户提交的输入方面的缺陷实现置换;
注入木马
- 在一个明显的攻击中,攻击者注入的功能向用户显示一个木马登录表单,要求他们像攻击者控制的服务器提交他们自己的证书。
# 2.6.XSS防御措施
# 输入验证
- 在输入的过程中,如果应用程序有向后端提交处理的数据,应对这些数据进行严格的确认;
- 比如:数据不能太长;
- 数据仅包含某组合法字符;
- 数据与一个特殊的正则表达式匹配(比如手机号);
- 根据应用程序希望在每个字段中收到的数据类型,尽可能限制性地对姓名、电子邮件地址、账号等应用不同的确认规则;
# 输出编码
- 如果应用程序将某位用户或第三方提交的数据复制到它的响应中,那么应用程序应对这些数据进行
HTML
编码,以净化可能的恶意字符; HTML
编码指用对应的HTML
实体替代字面量字符。这样做可确保浏览器安全处理可能为恶意的字符,把它们当作HTML
文档的内容而非结构处理;- 经常造成问题的字符的
HTML
编码:”
->"
'
->'
<
-><
>
->>
/
->x2F
应用程序之所以结合使用输入确认(次要)与输出净化(首要),原因在于这种方法能够提供两层防御:如果其中一层被攻破,另一层还能提供一些保护;
# 3.CSRF攻击
CSRF
(Cross-site Request Forgery
)跨站请求伪造,也被称为One Click Attack
或者Session riding
通常缩写为CSRF
或者XSRF
,是一种对网站的恶意利用;
尽管听起来像跨站脚本(XSS
),但它与XSS
非常不同,并且攻击方式几乎相左;
# 3.1.CSRF攻击原理
XSS
利用站点内的信任用户(受害者),而CSRF
通过伪装来自受信任用户的请求来利用受信用的网站;通过社会学的手段(如通过电子邮件发送一个链接)来蛊惑受害者进行一些敏感性的操作,如修改密码、修改
E-mail
、转账等,而受害者还不知道他已经中招;
# 3.2.CSRF攻击危害
CSRF
的破坏力依赖于受害者的权限;- 如果受害者只是个普通用户,则一个成功的
CSRF
攻击会危害用户的数据以及一些功能; - 如果受害者具有管理员权限,则一个成功的
CSRF
攻击甚至会威胁到整个网站的安全; - 与
XSS
攻击相比,CSRF
攻击往往不太流行,因此对其进行防范的资源也相当稀少,和难以防范; - 故被认为比
XSS
更具危险性,所以CSRF
在业内有个响当当的名字——沉睡的巨人
# 3.3.CSRF攻击的特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
- 跨站请求可以用各种方式:图片
URL
、超链接、CORS
、Form
提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
CSRF
通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。(比如博客留言)
# 3.4.CSRF攻击的过程
- 受害者登录
a.com
,并保留了登录凭证(Cookie
); - 攻击者引诱受害者访问了
b.com
; b.com
向a.com
(服务器)发送了一个请求:a.com/act=xx
。浏览器会默认携带a.com
发放的Cookie
;a.com
接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者(a.com
的用户)自己发送的请求;a.com
以受害者的名义执行了act=xx
;- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让
a.com
执行了自己定义的操;
# 3.5.CSRF攻击预防
CSRF
通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF
的防护能力来提升安全性。
上文中讲了CSRF
的两个特点:
CSRF
(通常)发生在第三方域名。CSRF
攻击者不能获取到Cookie
等信息,只是使用。
针对这两点,我们可以专门制定防护策略,如下:
- 阻止不明外域的访问
- 同源检测
Samesite Cookie
- 提交时要求附加本域才能获取的信息
CSRF Token
- 双重
Cookie
验证 - 增加确认操作
- 重新认证
# 增加确认操作
- 比如转账功能,当用户调用
API
进行转装的时候,弹出一个对话框,例如:你确认转帐200
元吗?即在浏览器上进行敏感操作时增加确认操作,确保是用户所为;
# 重新认证
- 在做一些重要敏感的操作时,要求用户重新输入密码进入二次验证,只有正确了才进行操作;这种做法显然更安全,但对于用户来说不是特别友好——毕竟是增加了异一步操作;
- 所以安全和易用性,有时候不得不做出取舍;
# 使用Token*
CSRF
的一个特征是,攻击者无法直接窃取到用户的信息(Cookie
,Header
,网站内容等),仅仅是冒用Cookie
中的信息。
而CSRF
攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF
攻击者无法获取到的Token
。服务器通过校验请求是否携带正确的Token
,来把正常的请求和攻击的请求区分开,也可以防范CSRF
的攻击。
验证过程
- 服务器端:在用户刚登陆的时候,产生一个新的不可预知的
CSRF Token
,并且把此Token
存放在用户的session
中。 - 在任何一个需要保护的表单中(转账,该密码),增加一个隐藏的字段来从服务器端获取和存放这个
Token
; - 提交请求的时候,在服务器端检查提交的
Token
与用户Session
中的Token
是否一致,如果一致,继续处理请求,不一致或者没有的话,就返回一个错误的信息给用户。 - 在用户退出或者
Session
过期的时候,用户信息(包括CSRF Token
)从Session
中移除并且销毁Session
。
参考资料:大话HTTP协议、《图解HTTP》、前端安全系列之二:如何防止CSRF攻击?