1 Web及网络基础
1.1 使用 HTTP 协议访问 Web
Web 使用一种名为 HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。 而协议是指规则的约定。可以说,Web 是建立在 HTTP 协议上通信的。
- 超文本:不局限于文本信息,包括文本、图片、音频、视频等
- 传输:客户端<->服务器 双向传递
- 协议:约定好的一套规则
1997年1月公布的 HTTP/1.1 是目前主流的 HTTP 协议版本。
1.2 TCP/IP的分层管理
为了理解 HTTP,我们有必要先了解一下TCP/IP 协议族。
通常使用的网络(包括互联网)是在 TCP/IP 协议族的基础上运作的。而 HTTP 属于于它内部的一个子集。
TCP/IP 协议族里重要的一点就是分层。以下为两种分层模型。TCP/IP四层模型以及OSI七层模型。
1.3 TCP/IP通信传输流
利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则向上往应用层走。
- 首先作为发送端的客户端在应用层 (HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求。
- 接着,为了传输方便,在传输层(TCP 协议)把从应用层接收到的数据(HTTP请求报文)进行分割,在各个报文上打上标记序号及端口号后转发给网络层。
- 在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层。
- 接收端的服务器在链路层接收到数据,按顺序往上层发送,当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP 请求。
1.4 与 HTTP关系密切的协议:IP、TCP、DNS
1.4.1 负责域名解析的DNS服务
DNS(Domain Name System)服务是和 HTTP 协议一样位于应用层的协议。它提供 域名<--->IP 地址 之间的解析服务。
IP和域名之间是多对多的映射关系
- 一个域名可以指向多个ip,用来做负载均衡(DNS服务商根据你的位置和运营商返回不同的解析结果,参见CDN的应用)
可以在终端ping www.baidu.com
通过ping得到一个域名对应的IP,baidu的IP有很多,所以ping www.baidu.com
可以得到不同的IP,一个域名对应的IP是由域名的所有者指定的。
更改 hosts可以手动指定域名对应的IP。mac中打开终端,sudo vim /etc/hosts
就可以手动指定域名对应的IP,我们将www.baidu.com的IP指定为本机地址。
再次在终端ping www.baidu.com
试试,发现IP地址变成本机地址了。浏览器如果还是能访问百度的话,是因为浏览器有DNS缓存,换一个浏览器就好。试验完还是改回来把,不然访问不了百度了。
- 同样一个ip可以被多个域名指向,例如大家所购买的虚拟主机。
1.4.2 确保可靠性的 TCP 协议
握手过程中使用了SYN (synchronize同步标志)和 ACK(acknowledgement确认标志)。
1.4.3 负责传输的 IP 协议
IP 协议的作用是把各种数据包传送给对方,IP 间的通信依赖 MAC 地址。我们使用IP层上的ARP协议,根据通信方的 IP 地址反查出对应的MAC地址。
IP 地址指明了节点被分配到的地址,MAC 地址是指网卡所属的固定地址。IP 地址可以和 MAC 地址进行配对。IP 地址可变,但 MAC 地址基本上不会更改。
无论哪台计算机或网络设备都无法全面掌握互联网中的细节。在到达通信目标前的中转过程中,计算机或路由器等网络设备只能获悉粗略的传输路线。而在进行中转时,会利用下一站中转设备的 MAC 地址来搜索下一个中转目标。
1.5 URI和URL
URI (Uniform Resource Identifier 统一资源标识符)
- Uniform 统一:规定统一的格式,如http: 或 ftp:
- Resource资源 :可标识的任何东西
- Identifier标识符:表示可标识的对象
URI由两个主要的子集构成
- URL:通过描述资源的位置来描述资源
- URN:通过名字来识别资源,和位置无关
端口是什么
- TCP或UDP协议的规则,一个端口对应一个服务,用端口区分不同的服务
- 0到1023号端口是保留端口(1024~65535的端口都可以使用),请背诵以下常用端口
- 21端口 ----FTP
- 80端口 ----HTTP
- 53端口 ----DNS
- 443端口 ----HTTPS
- 1080端口 ----SOCKS代理(翻墙时默认用1080端口)
2 简单的HTTP协议
2.1 请求和响应
请求必定由客户端(浏览器)发出,而服务器端回复响应。
2.1.1 服务器(Server)由两部分组成
- 硬件(一个cpu很牛内存很强的没有显示器的电脑)例如cpu128核 内存32g
- 软件(程序)例如阿里云服务器
2.1.2如何用命令行访问一个网页 / 如何得到响应
$ curl -L http://www.baidu.com
2.1.3 请求和响应报文的构成
请求报文由四部分构成:
1 请求行 (第一行)方法 路径 协议/版本号 例如 GET/ndex.html HTTP/1.1
2 请求首部 (n行) KEY1: VALUE1 形式
3 空行 (1行回车,用于表示第二部分结束,如果没有回车怎么知道第二部分over了)
4 消息体 (n行)内容随便,格式可在第二部分指定,当然也可以不指定,注意query string不是消息体 只是把请求行里的内容拿出来而已 GET方法约定俗成没有请求体
请求报文中的第二部分 2HTTP首部字段可细分以下三部分
- 请求首部字段
- 通用首部字段
- 实体首部字段
关于请求报文中的第四部分 4消息体(请求实体):
请求主体的内容由传输者定义,传递了客户端到服务器的内容,其格式可以任意指定。譬如实体中可以放参数的序列化形式( a = 1 & b = 2 这种),或者直接放表单对象( Form Data对象,上传时可以夹杂参数以及⽂件),等等。
响应报文由四部分构成:
1 状态行 (第一行) 协议/版本号 状态码 状态描述 例如 HTTP/1.1 200 OK
2 请求首部 (n行) KEY1: VALUE1 形式
3 空行 (1行回车)
4 消息体 (n行)Chrome会把第四部分内容放在response中显示
请求报文中的第二部分 2HTTP首部字段可细分以下三部分
- 响应首部字段
- 通用首部字段
- 实体首部字段
关于响应报文中的第四部分 4消息体(响应实体):
响应实体(主体)中,就是放服务端需要传给客户端的内容。⼀般现在的接口请求时,实体中就是对于的信息的json格式,⽽像⻚面请求这种,⾥面就是直接放了一个html字符串,然后浏览器器⾃己解析并渲染。
2.1.4 HTTP/1.1首部字段一览
HTTP首部规定了一个请求的约束和规则,以键值对的形式呈现。
HTTP 首部字段结构
首部字名: 字段值
HTTP 首部字段根据实际用途被分为以下 4 种类型。
- 通用首部字段:请求报文和响应报文两方都会使用的首部。
- 请求首部字段 :从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
- 响应首部字段:从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端额外的内容信息。
- 实体首部字段:针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。
下图各个参数是什么意思
2.2 HTTP方法
方法 | 描述 |
---|---|
GET | 从服务器获取资源,获取时提供的是参数(queryString) |
POST | 向服务器提交数据,传递表单资源就是POST。 |
HEAD | 获得报文首部。与 GET 相同,但只返回 HTTP 报头,不返回文档主体,用于确认URI的有效性及资源更新的日期时间等。 |
PUT | 往服务器上传资源。鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件,存在安全性问题,一般web网站不使用此方法,若配合web的安全验证机制,或者架构采用REST标准的网站,就可能开放使用此方法。 |
DELETE | 删除指定资源,是与PUT相反的方法。出于安全考虑,一般web网站不使用此方法,若配合web的安全验证机制,或者架构采用REST标准的网站,就可能开放使用此方法。 |
OPTIONS | 询问服务器支持的 HTTP 方法。 |
CONNECT | 要求采用隧道协议连接代理。该方法要求在于代理服务器通信时建立隧道,实现用隧道协议进行TCP通信,主要使用SSL(安全套接层)和TLS(传输层安全)协议把通信内容加密后经过网络传输。 |
TRACE: | 追踪路径。让web服务器端将之前的请求通信环回给客户端的方法。发送请求时,在Max-Frowards首部字段中填入数值,每经过一个服务器端就-1,当数值为0时,停止传输,最后收到服务器返回状态码200 OK的响应。该方法很容易引起XST(跨站追踪)攻击,很少用到。 |
2.2.1 GET和POST的区别
GET用于从服务器端获取数据,包括静态资源(HTML|JS|CSS|Image等等)、动态数据展示(列表数据、详情数据等等)。
POST用于向服务器提交(更新)数据,比如增删改数据,提交一个表单新建一个用户、或修改一个用户等。
你能用GET进行更新操作,也能用POST进行查询操作 ,但是那不是这俩Method的本意。前者是获取、 后者是更新。获取时提供的是参数(queryString) 更新则是表单 。
幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同。
比较方面 | GET | POST |
---|---|---|
后退按钮/刷新(幂等性) | 无害(幂等) | 数据会被重新提交(浏览器应该告知用户数据会被重新提交,POST语义不是幂等的,重复请求可能会带来意想不到的后果。) |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
历史 | 参数保留在浏览器历史中 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | GET传递的参数只能带URL后面,文本格式QueryString,各浏览器一般有长度限制(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分,可以直接看到,明文传输。GET请求会保存在浏览器历史纪录或 web 服务器日志中。 | POST是通过header请求,可以开发者工具或者抓包可以看到,同样也是明文的,请求不会保留在浏览器历史记录中。 |
是否改变服务器状态 | 否,get多少次都不应改变页面呈现的数据,而post会 | 是 |
2.3 长连接(持久连接) 与短连接
短连接:http1 . 0 中,默认使⽤用的是短连接,也就是说,浏览器器每进⾏一次http操作,就建⽴一次连接,任务结束就中断连接,譬如每一个静态资源请求都是一个单独的连接。
长连接:http1.1起,默认使用⻓连接,使⽤长连接会有这⼀行 Connection:keep-alive,⼀个tcp/ip连接上可以连续发送多个数据包。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。
2.4 使用Cookie进行用户识别及状态管理
HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行处理。每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。由于不必保存状态,自然可减少服务器的CPU及内存资源的消耗,这是为了更快地处理大量事务。
HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能, 于是引入了 Cookie 技术。Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。cookie是浏览器器的一种本地存储⽅方式,用来帮助客户端和服务端通信的,常用来进⾏身份校验,结合服务端的session使用。
Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再次向该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。
服务器端发现客户端发送过来的 Cookie 后,会先检查是从哪 一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。
HTTP 请求报文和响应报文的内容如下。
下面的表格列举了 Set-Cookie 的字段值。
Chrome开发者工具的Applications里面可以看到cookie信息
每个cookie的信息条目有:Name Value Domain Path Expires Size HTTP 等
2.5 Session管理及Cookie应用(用于实现Session的一种方式)
- 由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session。Session被保存在服务端的内存、数据库、文件中,有一个唯一标识即Session ID。
- 服务端如何识别特定的客户?这个时候Cookie就登场了。在第一次创建Session的时候,服务端会在首部字段 Set-Cookie 内写入 Session ID(如 PHPSESSID=028a8c...)。以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。客户端接收到从服务器端发来的Session ID后,会将其作为 Cookie 保存在本地。下次发送HTTP请求的时候,浏览器会自动发送Cookie,Session ID也随之发送到服务器。服务器通过配对接收到的Session ID获取Session内容,识别用户和其认证状态。
由此可见,Session 的运行依赖 Session ID,而 Session ID 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie ,同时 Session 也会失效(但可以通过其它方式实现,比如在 URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户)。 - Cookie还可以用于其他方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。
2.6 HTTP状态码
当客户端向服务器端发送请求时,状态码用于描述请求的处理结果。
2.6.1 具有代表性的14个状态码
- 200 OK 请求已正常处理
- 204 No Content 请求处理成功,但没有资源可返回。(如果用户定期刷新页面,就可以返回204)
- 206 Partial Content 客户端进行连范围请求,而服务器成功执行连这部分的GET请求,响应报文中包含由Content -Range指定范围的实体内容。
- 301 Moved Permanently 永久重定向
客户请求的资源已被分配了新的 URI,浏览器应该自动地访问新的URL。如果已经把资源对应的 URI 保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。 - 302 Found(Moved Temporatily )临时重定向
客户请求的资源已被分配了新的 URI,希望浏览器本次使用新的URI访问。302 状态码代表的资源不是被永久移动,只是临时性质的。如果已经把资源对应的 URI 保存为书签了,不会像301状态码出现时那样去更新书签。 - 303 See Other 和 302 Found类似,临时按新的URI访问,但303明确表示客户端应当使用 GET 方法获取资源,这点与302不同。
- 304 Not Modified 协商缓存返回304状态码,服务器告诉客户端:原来缓存的文档还可以继续使用。如果客户端发送了一个带条件的GET请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。
- 400 Bad Request 表示请求报文中存在语法错误。
- 401 Unauthorized
该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、 DIGEST认证)的认证信息。另外若之前已进行过 1 次请求,表示用户认证失败。
- 403 Forbidden
对请求资源的访问被服务器拒绝了。通常由于服务器上文件或目录的权限设置导致。 - 404 Not Found
无法找到指定位置的资源。出现这个错误的最有可能的原因是服务器端没有这个页面。 - 500 Internal Server Error
服务器端在执行请求时发生了错误。一般来说,这个问题都会在服务器端的源代码出现错误时出现。 - 503 Service Unavailable
服务器由于维护或者负载过重未能应答。这个状况是临时的,并且将在一段时间以后恢复。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个 Retry-After头。
301 和 302 的区别是什么?
301 永久重定向,浏览器会记住重定向的结果
302 临时重定向 ,浏览器不会记住的
301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved Temporatily”。出现该状态代码时,浏览器能够自动访问新的URL,因此它是一个很有用的状态代码。注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求http://host/~user(缺少了后面的斜杠),有的服务器 返回301,有的则返回302。严格地说,我们只能假定只有当原来的请求是GET时浏览器才会自动重定向。请参见307。
3 确保 Web 安全的 HTTPS
3.1 HTTP 的缺点
- 通信使用明文(不加密),内容可能会被窃听
- 不验证通信方的身份,因此可能遭遇伪装
- 无法证明报文的完整性,所以可能已遭篡改
3.2 HTTP+加密+认证+完整性保护=HTTPS
HTTPS是身披SSL(Secure Socket Layer)外壳的HTTP,通常HTTP直接和TCP通信,当使用SSL时,就演变成先和SSL通信,再由 SSL 和 TCP 通信了。
在采用 SSL 后,HTTP 就有了 HTTPS 的加密、证书和完整性保护这些功能。SSL 是独立于 HTTP 的协议,所以不光是 HTTP 协议,其他运行在 应用层的 SMTP 和 Telnet 等协议均可配和 SSL 协议使用。可以说 SSL 是当今世界上应用最为广泛的网络安全技术。
3.3 HTTPS采用混合加密机制
HTTPS 采用共享密钥加密(对称加密)和公开密钥加密(非对称加密)两者并用的混合加密机制。
- 公开密钥加密相比共享密钥加密,其处理速度慢了很多。
- 以共享密钥加密方式加密时必须将密钥也发给对方。在互联网上转发密钥时,如果通信被监听那么密钥就可会落入攻击者之手,同时也就失去了加密的意义。
因此充分利用两种加密机制各自优势, 在交换密钥环节使用公开密钥加密方式,之后的建立通信交换报文阶段则使用共享加密方式。
3.4 证明公开密钥正确性的证书
公开密钥加密方式还是存在一些问题的。那就是无法证明公开密钥本身就是货真价实的所预想的那台服务器发行的公开密钥,或许在公开密钥传输途中,真正的 公开密钥已经被攻击者替换掉了。
为了证明公开密钥的正确性,可以使用由数字证书认证机构(CA,Certificate Authority)和其相关机关颁发的公开密钥证书。流程如下:
- 服务器的运营人员向数字证书认证机构提出公开密钥的申请---->数字证书认证机构在判明申请者的身份后,会用自己的私钥对服务器的公开密钥部署数字签名,颁发公钥证书(服务器的公开密钥+数字签名)
- 服务器将该公钥证书发送给客户端。
- 客户端拿到公钥证书,使用数字证书认证机构发布的公钥(浏览器会事先内部植入常用认证机关的公钥)验证公钥证书上的数字签名,以确认服务器公开密钥的真实性。
3.5 HTTPS 的问题:处理速度慢
SSL 的慢分两种。
- 通信慢:除去和TCP连接、发送HTTP请求、响应外,还需进行SSL通信。
- 由于大量消耗 CPU 及内存等资源,导致处理速度变慢:SSL在客户端和服务器都要进行加密解密的运算,比起HTTP会更多消耗服务器和客户端的硬件资源。
因此,如果是非敏感信息则使用 HTTP 通信,只有在包含个人信息等敏感数据时,采利用 HTTPS 加密通信。
4 基于 HTTP 的协议
4.1 HTTP通信的瓶颈
以下这些 HTTP 标准成为了网站性能的瓶颈。
- 一条连接上只可发送一个请求
- 请求只能从客户端开始,客户端不可以接收除了响应以外的指令
- 请求 / 响应首部未经压缩就发送。首部信息越多延迟越大。
- 每次互相发送相同的首部造成的浪费较多。
- 可任意选择数据压缩格式。非强制压缩发送。
4.2 利用WebSocket实现浏览器和服务器间的全双工通信
WebSocket,即 Web 浏览器与 Web 服务器之间全双工通信标准。一但Web 服务器与客户端之间建立起 WebSocket 协议的通信连接, 之后所有的通信都依靠这个专用协议进行。通信过程中可互相发送 JSON、XML、HTML 或图片等任意格式的数据。
WebSocket 协议的两个主要特点。
- 推送功能:支持由服务器向客户端推送数据的推送功能。这样,服务器可直接发送数据,而不必等待客户端的请求。
- 减少通信量:
只要建立起 WebSocket 接,就希望一直保持连接状态。和 HTTP 相比,不但每次连接时的总开销减少,而且由于 WebSocket 的首部信息很小,通信量也相应减少了。
4.2.1WebSocket 通信的实现
为了实现 WebSocket 通信,在 HTTP 连接建立之后,需要握手请求和握手响应。
握手请求
使用 HTTP 的 Upgrade 首部字段, 告知服务器通信协议发生改变,以达到握手的目的。
握手响应
成功握手确立 WebSocket 连接之后,通信时不再使用 HTTP 的数据帧,而是用 WebSocket 独立的数据帧。
4.2.2 WebSocket API
JavaScript 可调用The WebSocket API,以 现 WebSocket 协议的全双工通信。
5 浏览器缓存
浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。前后端的http交互中,使⽤缓存能很大程度上的提升效率。
5.1强缓存与协商缓存
缓存可以划分为强缓存与协商缓存两种类型,区别如下:
- 强缓存( 200 fromcache)时,浏览器如果判断本地缓存未过期,不用请求服务器直接使用本地缓存
- 协商缓存( 304)时,浏览器器会向服务端发起http请求,然后服务端告诉浏览器缓存未过期,让浏览器使用本地缓存
对于协商缓存,使⽤ Ctrl +F5强制刷新可以使得缓存无效。但是对于强缓存,在未过期时, 必须更更新资源路路径才能发起新的请求(更改了资源路径相当于是请求另一个资源了)
5.2 通过不同的http头部区分强缓存与协商缓存
5.2.1强缓存
(http1.0) Pragma/Expires
(http1.1) Cache-Control/Cache-Control
- Pragma: no-cache 可以让本地强缓存失效
只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。 - Expires: 服务端配置的,属于强缓存,⽤用来控制在规定的时间之前,浏览器器不会发出请求,⽽是直接使⽤用本地缓存,Expires一般对应服务器端时间,如 Expires : Fri , 30 Oct 1998 14:19:41
- Cache-Control:通用首部字段,HTTP1.1中启用Cache-Control来控制页面的强缓存与否,指令参数是可选的,多个指令之间通过“,”分割
Cache-Control: private, max-age=0, no-cache
关于no-cach和no-store的说明
no-cache表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存
no-store ,真正的不缓存任何东西。浏览器会直接向服务器请求原始文件,并且请求中不附带 Etag 参数(服务器认为是新请求)。
1.1Cache-Control:max-age 的优先级高于1.0Expires
Expires 使⽤的是服务器端的时间,有时候会有这样一种情况-客户端时间和服务端不同步。这样可能会造成浏览器本地的缓存无⽤或者⼀直⽆法过期,所以http1.1后不推荐使⽤Expires。⽽ Max-Age使⽤的是客户端本地时间计算,不会有这个问题。
应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Cache-Control:max-age 和Expires 首部字段的情况时,会优先处理理 max-age 指令,而忽略 Expires 首部字段。
1.1Cache-Control和1.0Pragma
Pragma 是 HTTP/1.1 之前版本的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义。因此,发送的请求会同时含有下面两个首部字段。
Cache-Control: no-cache
Pragma: no-cache
5.2.2 协商缓存
(http1.0) If-Modified-Since/Last-Modified
(http1.1) If-None-Match/E-tag
-
If-Modified-Since:告知服务器若 If-Modified-Since 字段值早于资源的更新时间Last-Modified,则希望能处理该请求。而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源都未有过更新,则返回状态码 304 Not Modified。
- If-None-Match:指定当 If-None-Match 字段值的实体标记(ETag) 值与请求资源的 ETag 不一致时,它就告知服务器处理该请求。
- Last-Modified :
1.表明服务端的⽂文件最后何时改变的
2.缺陷1:就是只能精确到1s,
3.缺陷2:有的服务端的⽂件会周期性的改变,导致缓存失效 - E-tag:
1.是一种指纹机制,代表文件相关指纹
2.只有文件变才会变,也只要⽂件变就会变,
3.没有精确时间的限制,只要⽂件⼀改变,E-tag就不一样了
1.1E-tag相⽐比1.0Last-Modified
Etag 主要为了解决 Last-Modified 无法解决的一些问题。
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s(秒)级的,这种修改无法判断。
- 某些服务器不能精确的得到文件的最后修改时间;
为此,HTTP/1.1引入了 Etag(Entity Tags实体标记).Etag仅仅是一个和文件相关的标记, 比如说v1.0.0或者说"2e681a-6-5d044840"这么一串看起来很神秘的编码。但是HTTP/1.1标准并没有规定Etag的内容是什么或者说要怎么实现。
5.3 浏览器使用缓存的工作流程
浏览器在第一次请求发生后,再次请求时:
- 浏览器会先获取该资源缓存的header信息,根据其中的expires和cahe-control判断是否命中强缓存
- 若命中则直接使用本地缓存,不用请求服务器。
- 如果没有命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服务器根据请求中的相关header信息来对比结果是否命中协商缓存
- 若命中,则服务器返回新的响应header信息更新缓存中的对应header信息,但是并不返回资源内容,它会告知浏览器可以直接从缓存获取;
- 未命中,从服务器返回最新的资源内容
6 Web安全之攻击技术
对 Web 应用的攻击模式有以下两种。
- 主动攻击
攻击者通过直接访问 Web 应用,把攻击代码传入的攻击方式。由于该方式是直接针对服务器上的资源进行攻击,因此攻击者需要能够访问到那些资源。例如SQL注入攻击和OS命令注入攻击 - 被动攻击
利用圈套策略行攻击代码的攻击模式。攻击者不直接对目标 Web 应用访问发起攻击。例如XSS和CSRF。
6.1 什么是 XSS 攻击?如何预防?
XSS( Cross site scripting,跨站脚本攻击)利用的是浏览器可以拼接成任意的javascript,然后攻击者编写恶意脚本(即拼接好javascript)让浏览器自动地给服务器端发出多个请求(get、post请求),当其他用户在自己浏览器上运行时,一不小心就会遭到被动攻击。简单来说就是恶意用户 H 提交恶意脚本,显示在另一个用户 B 的网页上,对 B 的网页随意篡改。
6.1.1造成 XSS 有几个要点:
- 恶意用户可以提交内容
- 提交的内容可以显示在另一个用户的页面上
- 这些内容未经过滤,直接运行在另一个用户的页面上
6.1.2 XSS可能造成以下影响:
利用虚假输入表单骗取用户个人信息
窃取用户Cookie信息
6.1.3 XSS攻击举例说明
假设我们有一个评论系统。
用户 A 提交评论「小谷你好」到服务器,然后用户 B 来访问网站,看到了 A 的评论「小谷你好」,这里没有 XSS。
恶意用户 H 提交评论「<script>console.log(document.cookie)</script>」,然后用户 B 来访问网站,这段脚本在 B 的浏览器直接执行,恶意用户 H 的脚本就可以任意操作 B 的 cookie,而 B 对此毫无察觉。有了 cookie,恶意用户 H 就可以伪造 B 的登录信息,随意访问 B 的隐私了。而 B 始终被蒙在鼓里。
6.1.4 预防XSS的3个方法
- 不要使用 innerHTML,改成 innerText,这样script 就会被当成文本,不会执行
- 如果你一定要用 innerHTML,就要把可疑符号变成 HTML 实体
把 < 替换成 <
把 > 替换成 >
把 & 替换成 &
把 " 替换成 '
把 ' 替换成 "
代码 div.innerHTML = userComment.replace(/>/g, '<').replace...
- Chrome浏览器使用 CSP (Content Security Policy内容安全策略)
CSP通过黑白名单的机制控制资源加载(或执行脚本)。
6.2 什么是 CSRF 攻击?如何预防?
CSRF(Cross Site Request Forgery, 跨域请求伪造)利用的是网站服务器端所有参数都是可预先构造的原理,然后黑客拼接好具体请求url(构造网站后台某个功能接口的请求地址,即设置好陷阱),利用已通过认证的用户权限,诱导用户去点击或者用特殊方法让该请求地址自动加载,在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点。由于用户在登录状态下,所以这个请求被服务端接收后会被误以为是用户合法的操作。
6.2.1 CSRF攻击过程
1.用户访问浏览正常网站
2.正常网站服务器响应并且返回标识该用户身份的cookie
3.用户未注销正常网站的情况下,访问恶意网站
4.恶意网站里访问正常网站并且带着标识用户的cookie
5.正常网站服务器接受来自恶意网站的请求
6.2.2 CSRF攻击举例说明
a.用户在 qq.com 登录
b.攻击者设置好陷阱,诱导用户切换到 hacker.com(恶意网站)
c.hacker.com 发送一个 qq.com/add_friend 请求,让当前用户添加 hacker 为好友。 虽然有跨域,但跨域并不阻止发送请求,只阻止接受响应
d.用户在不知不觉中添加 hacker 为好友。
e.用户没有想发这个请求,但是 hacker 伪造了用户发请求的假象。
6.2.3 预防的2个方法
1.检查 http referer字段
(HTTP Referer是header的一部分,它记录了该 HTTP 请求的来源地址),qq.com 可以拒绝来自 hacker.com 的请求。
优点:简单易行,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。
缺点:1.Referer 的值是由浏览器提供的,使用验证 Referer 值的方法,就是把安全性都依赖于浏览器来保障,理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。
2.由于Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。网站不能因为请求没有 Referer 值而认为是 CSRF 攻击,从而拒绝合法用户的访问。
2.添加校验 csrf_token 来解决
- 当用户正常访问网站时,服务器会生产一个随机数token,并且把该随机数埋入该页面里(一般放在form表单,<input type="hidden" name="_csrf_token" value="xxxx">)发送给客户端。
- 正常访问,客户的浏览器能够得到该token。
- 客户端提交请求时,需要返回该token到服务器(对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成
http://url?csrftoken=tokenvalue
。对于 POST 请求来说,要在 form 的最后加上<input type=”hidden” name=”csrftoken” value=”tokenvalue”/>
)。 - 服务端检测这个TOKEN是否是合法的(把请求中的 token 与session 中的 token 进行比对(解析请求的cookie获取sessionid,获取session中_csrf_token的值,然后和用户请求提交的_csrf_token做个比较,如果相等表示请求是合法的),如果不合法就有可能是黑客伪造用户信息进行请求的。