HTTP协议简介
Http是超文本传输协议(Hyper Text Transfer Protocol)的缩写,是用于Web服务器传输数据到本地浏览器的一种协议。HTTP协议于1990年提出,目前主流使用的是HTTP 1.1版本协议,旧版本为1.0,最新版本为2.0。
HTTP协议归属于网络七层协议的应用层协议,基于TCP/IP协议。也就意味着HTTP的建立流程和普通的Socket连接并无差别,都需要进行三次握手,差别在于HTTP协议规定了Socket连接以后通信的基本数据格式,而这种格式就是HTTP协议。
网络七层模型
http协议工作于客户端-服务器架构之上。客户端其请求,服务器会送响应,请求和响应是一对一匹配的。
HTT连接是短链接(无连接)的,每个连接每次只处理一个请求,响应完毕候立即断开连接。目前短链接也更多体现在逻辑层面,而物理层面可以通过配置HTTP的请求头参数来设定底层物理连接不断开。
HTTP协议是无状态的,请求客户端和服务器都不会记录请求事务的上下文,意味着后续业务请求如果依赖之前的信息,就需要重新传送这些信息。
HTTP默认的端口是80,HTTPS的默认端口是443.
HTTP可以用来传递任何数据,例如:二进制,字符串,文件等等。HTTP最主要的客户端是浏览器,大部分的网络API都是使用HTTP请求模型。
HTTP流程
如果是HTTPS格式,建立完毕TCP连接以后还会进行密钥协商流程。
HTTP请求-协议格式
http请求协议格式:
回车符:\r
换行符:\n
使用WireShark等抓包工作,能够得到的一个示例报文如下:
HTTP请求-HTTP方法
序号 |
Method |
方法说明 |
备注 |
1 |
GET |
请求指定资源,参数放置在url之后 |
|
2 |
POST |
向指定资源提交数据,数据放置在body部分 |
|
3 |
PUT |
更新资源内容 |
|
4 |
DELTE |
删除资源 |
|
5 |
OPTIONS |
返回服务器针对特定资源所支持的HTTP请求方法 |
|
6 |
TRACE |
回显服务器收到的请求 |
|
7 |
HEAD |
只返回响应的头 |
|
8 |
CONNECT |
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
HTTP请求-URL
URL(Uniform Resource Locator)是统一资源定义标识符的简写,用来定义互联网上某个资源地址
http的url基本格式为:http://domain:port/path?key=value#param。
例如:http://127.0.0.1:8080/demo/index.jsp?name=seagle&pwd=123#tag
URL各部分的含义:
1. 协议部分:“http”代表http协议,其它还有ftp,tftp等。
2. 域名部分:127.0.0.1代表服务器地址,可以是域名也可以是IP地址。
3. 端口部分:8080代表服务器的一个端口,端口是可选的,如果没有端口默认使用80端口。
4. 资源路径:/dome/index.jsp。/demo/代表者资源的虚拟目录,index.jsp代表访问的资源文件或。
5.参数部分:如果有问号“?”则从“?”到“#”之间的是参数,参数使用&进行分割。
6.锚部分:锚放置在参数之后,从“#”开始到URL结束部分都是锚,例如tag。
HTTP请求-Header
序号 |
key |
value |
说明 |
备注 |
1 |
Accept |
Accept: text/plain, text/html |
指定客户端能够接收的内容类型 |
|
2 |
Accept-Charset |
Accept-Charset: iso-8859-5 |
浏览器可以接受的字符编码集。 |
|
3 |
Accept-Encoding |
Accept-Encoding: compress, gzip |
指定浏览器可以支持的web服务器返回内容压缩编码类型。 |
|
4 |
Accept-Language |
Accept-Language: en,zh |
浏览器可接受的语言 |
|
5 |
Accept-Ranges |
Accept-Ranges: bytes |
可以请求网页实体的一个或者多个子范围字段 |
|
6 |
Authorization |
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
HTTP授权的授权证书 |
|
7 |
Cache-Control |
Cache-Control: no-cache |
指定请求和响应遵循的缓存机制 |
|
8 |
Connection |
Connection: close |
表示是否需要持久连接。(HTTP 1.1默认进行持久连接) |
|
9 |
Cookie |
Cookie: $Version=1; Skin=new; |
HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 |
|
10 |
Content-Length |
Content-Length: 348 |
请求的内容长度 |
|
11 |
Content-Type |
Content-Type: application/x-www-form-urlencoded |
请求的与实体对应的MIME信息 |
|
12 |
Date |
Date: Tue, 15 Nov 2010 08:12:31 GMT |
请求发送的日期和时间 |
|
13 |
Expect |
Expect: 100-continue |
请求的特定的服务器行为 |
|
14 |
From |
From: [email protected] |
发出请求的用户的Email |
|
15 |
Host |
Host: www.zcmhi.com |
指定请求的服务器的域名和端口号 |
|
16 |
If-Match |
If-Match: “737060cd8c284d8af7ad3082f209582d” |
只有请求内容与实体相匹配才有效 |
|
17 |
If-Modified-Since |
If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 |
|
18 |
If-None-Match |
If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 |
|
19 |
If-Range |
If-Range: “737060cd8c284d8af7ad3082f209582d” |
如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag |
|
20 |
If-Unmodified-Since |
If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
只在实体在指定时间之后未被修改才请求成功 |
|
21 |
Max-Forwards |
Max-Forwards: 10 |
限制信息通过代理和网关传送的时间 |
|
22 |
Pragma |
Pragma: no-cache |
用来包含实现特定的指令 |
|
23 |
Proxy-Authorization |
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
连接到代理的授权证书 |
|
24 |
Range |
Range: bytes=500-999 |
只请求实体的一部分,指定范围 |
|
25 |
Referer |
先前网页的地址,当前请求网页紧随其后,即来路 |
||
26 |
TE |
TE: trailers,deflate;q=0.5 |
客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 |
|
27 |
Upgrade |
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
向服务器指定某种传输协议以便服务器进行转换(如果支持) |
|
28 |
User-Agent |
User-Agent: Mozilla/5.0 (Linux; X11) |
User-Agent的内容包含发出请求的用户信息 |
|
29 |
Via |
Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
通知中间网关或代理服务器地址,通信协议 |
|
30 |
Warning |
Warn: 199 Miscellaneous warning |
关于消息实体的警告信息 |
HTTP响应-协议格式
回车符:\r
换行符:\n
使用WireShark等抓包工作,能够得到的一个示例报文如下:
HTTP响应-响应码
http的响应码是由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后面的数字定义了具体的状态信息:
状态码分类 |
状态码分类描述 |
1** |
信息,服务器收到请求,需要请求者继续执行操作 |
2** |
成功,请求成功收到且成功处理 |
3** |
重定向,需要进一步操作以完成请求任务 |
4** |
客户端错误,请求包含语法错误或者无法完成的请求 |
5** |
服务器错误,服务器在处理请求的过程中发生了错误 |
http详细的状态码说明:
响应码 |
消息 |
描述 |
100 |
Continue |
继续,客户端应该继续其请求 |
101 |
Switching Protocols |
切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 |
OK |
请求成功。一般用于GET与POST请求 |
201 |
Created |
已创建。成功请求并创建了新的资源 |
202 |
Accepted |
已接受。已经接受请求,但未处理完成 |
203 |
Non-Authoritative Information |
非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 |
No Content |
无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 |
Reset Content |
重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 |
Partial Content |
部分内容。服务器成功处理了部分GET请求 |
300 |
Multiple Choices |
多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 |
Moved Permanently |
永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 |
Found |
临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 |
See Other |
查看其它地址。与301类似。使用GET和POST请求查看 |
304 |
Not Modified |
未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 |
Use Proxy |
使用代理。所请求的资源必须通过代理访问 |
306 |
Unused |
已经被废弃的HTTP状态码 |
307 |
Temporary Redirect |
临时重定向。与302类似。使用GET请求重定向 |
400 |
Bad Request |
客户端请求的语法错误,服务器无法理解 |
401 |
Unauthorized |
请求要求用户的身份认证 |
402 |
Payment Required |
保留,将来使用 |
403 |
Forbidden |
服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 |
Not Found |
服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
405 |
Method Not Allowed |
客户端请求中的方法被禁止 |
406 |
Not Acceptable |
服务器无法根据客户端请求的内容特性完成请求 |
407 |
Proxy Authentication Required |
请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 |
Request Time-out |
服务器等待客户端发送的请求时间过长,超时 |
409 |
Conflict |
服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 |
Gone |
客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 |
Length Required |
服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 |
Precondition Failed |
客户端请求信息的先决条件错误 |
413 |
Request Entity Too Large |
由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 |
Request-URI Too Large |
请求的URI过长(URI通常为网址),服务器无法处理 |
415 |
Unsupported Media Type |
服务器无法处理请求附带的媒体格式 |
416 |
Requested range not satisfiable |
客户端请求的范围无效 |
417 |
Expectation Failed |
服务器无法满足Expect的请求头信息 |
500 |
Internal Server Error |
服务器内部错误,无法完成请求 |
501 |
Not Implemented |
服务器不支持请求的功能,无法完成请求 |
502 |
Bad Gateway |
充当网关或代理的服务器,从远端服务器接收到了一个无效的请求 |
503 |
Service Unavailable |
由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 |
Gateway Time-out |
充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 |
HTTP Version not supported |
服务器不支持请求的H |
比较场景的HTTP响应码:
l 200 - 请求成功
l 301 - 资源(网页等)被永久转移到其它URL
l 404 - 请求的资源(网页等)不存在
l 500 - 内部服务器错误
HTTP响应-Header
Header |
描述 |
示例 |
Accept-Ranges |
表明服务器是否支持指定范围请求及哪种类型的分段请求 |
Accept-Ranges: bytes |
Age |
从原始服务器到代理缓存形成的估算时间(以秒计,非负) |
Age: 12 |
Allow |
对某网络资源的有效的请求行为,不允许则返回405 |
Allow: GET, HEAD |
Cache-Control |
告诉所有的缓存机制是否可以缓存及哪种类型 |
Cache-Control: no-cache |
Content-Encoding |
web服务器支持的返回内容压缩编码类型。 |
Content-Encoding: gzip |
Content-Language |
响应体的语言 |
Content-Language: en,zh |
Content-Length |
响应体的长度 |
Content-Length: 348 |
Content-Location |
请求资源可替代的备用的另一地址 |
Content-Location: /index.htm |
Content-MD5 |
返回资源的MD5校验值 |
Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Range |
在整个返回体中本部分的字节位置 |
Content-Range: bytes 21010-47021/47022 |
Content-Type |
返回内容的MIME类型 |
Content-Type: text/html; charset=utf-8 |
Date |
原始服务器消息发出的时间 |
Date: Tue, 15 Nov 2010 08:12:31 GMT |
ETag |
请求变量的实体标签的当前值 |
ETag: “737060cd8c284d8af7ad3082f209582d” |
Expires |
响应过期的日期和时间 |
Expires: Thu, 01 Dec 2010 16:00:00 GMT |
Last-Modified |
请求资源的最后修改时间 |
Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT |
Location |
用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 |
Location: http://www.zcmhi.com/archives/94.html |
Pragma |
包括实现特定的指令,它可应用到响应链上的任何接收方 |
Pragma: no-cache |
Proxy-Authenticate |
它指出认证方案和可应用到代理的该URL上的参数 |
Proxy-Authenticate: Basic |
refresh |
应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) |
Refresh: 5; url=http://www.zcmhi.com/archives/94.html |
Retry-After |
如果实体暂时不可取,通知客户端在指定时间之后再次尝试 |
Retry-After: 120 |
Server |
web服务器软件名称 |
Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) |
Set-Cookie |
设置Http Cookie |
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
Trailer |
指出头域在分块传输编码的尾部存在 |
Trailer: Max-Forwards |
Transfer-Encoding |
文件传输编码 |
Transfer-Encoding:chunked |
Vary |
告诉下游代理是使用缓存响应还是从原始服务器请求 |
Vary: * |
Via |
告知代理客户端响应是通过哪里发送的 |
Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning |
警告实体可能存在的问题 |
Warning: 199 Miscellaneous warning |
WWW-Authenticate |
表明客户端请求实体应该使用的授权方案 |
WWW-Authenticate: Basic |
HTTPS
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)是http的安全通信版本,基于SSL实现。普通的HTTP在进行通信的时候是明文传输的容易被抓包,拦截等风险。
使用HTTPS,通信的内容是加密的,就算被抓包也无法得知通信内容。HTTPS的基本通信流程为:
1.客户端与服务器建立Socket连接。
2.客户端请求服务器。
3.服务器将其公钥证书发送给客户端。
4.客户端验证公钥证书是否有效。
5.客户端生成一个随机数,称之为通信密钥(对称加密密钥)。
6.客户端使用公钥对这个通信密钥进行加密。
7.客户端把加密后的通信密钥发给服务器。
8.服务器使用其私钥解密这个通信密钥。
9.之后客户端与服务器直接的通信数据都使用这个通信密钥进行加密后传输。
https流程:
在上传流程中有一步,验证密钥合法性,有两种场景的验证方式:
1.服务器的证书是全球信任的证书颁发机构颁发的。
这种场景下,证书的验证一般可以由浏览器或者其它系统自己的验证策略。基本的验证策略流程:
第一:检查SSL证书是否安全可信。先确定是否由受信任的根证书颁发机构颁发,再验证证书的签名是否正确,验证通过后说明证证书内容是可以安全可信且没有被修改过。
第二:检查SSL证书中的证书吊销列表,检查证书是否被证书颁发机构吊销。
第三:检查此SSL证书是否过期。证书中都包含了过期时间。
第四:检查部署此SSL证书的网站的域名是否与证书中的域名一致。
第五:IE7浏览器会到欺诈网站数据库查询此网站是否已经被列入欺诈网站黑名单。
浏览器需经过以上5个方面的检查后,就可以判断该证书的是有效可信的。
这里面有个核心点就是域名验证,因为一个域名同一个CA架构之允许申请一个证书,所以如果一个中间人攻击者想要进行通信拦截,有两种办法以及两种规避点:
第一种:伪造证书,如果中间人修改服务器下发的正确证书中的公钥,就会造成签名验证不通过。
第二种:替换证书,如果中间人拦截了服务器下发的证书,然后替换成自己从CA机构申请的证书,那么在验证域名的证书信息的时候就会和请求的域名不一致造成验证不通过。
2.服务器的证书是私有证书。
这种场景,如果依赖浏览器或者系统自带证书验证策略肯定是不行的,第一条就验证不通过,这就需要在客户端集成证书。例如我们在浏览12306网站的时候,就会自动下载一个证书并要求信任此证书,证书会加入到系统证书列表中,当然这种方式并不是特别的安全。
对于移动端开发来讲,需要开发人员提供验证策略。
HTTP文件上传
http支持文件上传的类别包括:
1.单个文件上传。
2.多个文件上传。
3.文件与参数同时上传。
在前面有说明,HTTP只是一种通信格式,数据的传输还是基于TCP的Socket。所以文件上传的基本原理还是将文件的二进制数据放在HTTP协议中然后一起发送给服务器。通过抓包分析可以得到Http文件上传的基本格式:
这个例子里面,上传一个名称为1.log的文件并同时提交了两个参数:ip=210.21.220.218和random=1524107835295
以此例子可以发现文件上传的几个特点:
1.Content-Type必须为multipart/fort-data;boundary=分隔符
2.每个参数无论是文件,参数都是使用--boundary的进行分割的(注意每个分隔符都是:--+boundary)。
3.每个独立的参数都需要使用Content-Disposition:form-data;name=参数名称,文件还必须增加一个filename=文件名称。
4.请求必须是POST的方式。
5.每个参数都可以理解是POST的独立body,与每个参数的头部空一行。
6.请求结尾使用--boundary--结束。
因此http上传文件的时候按照以上要求构建请求头和请求体即可。
HTTP Cookies
http是无状态协议,也就是说两次请求是独立。但是对于一些需要权限验证的地方,例如系统登陆,就需要一定机制来验证用户的登陆状态。
Cookies是服务器给客户的请求分配的一个唯一表示,在服务器端标识为session,服务器将这个标识发送给客户端,客户端保存这个标识,在以后每次请求的时候都带上
这个标识,就可以知道客户端之前请求过什么,现在状态如何。
Cookies的结构
l Domain:域,表示当前cookie所属于哪个域或子域下面。对于服务器返回的Set-Cookie中,如果没有指定Domain的值,那么其Domain的值是默认为当前所提交的http的请求所对应的 主域名的。比如访问 http://www.example.com,返回一个cookie没有指名domain值,那么其为值为默认的www.example.com。
l Path:表示cookie的所属路径。
l Expire time/Max-age:表示了cookie的有效期。expire的值,是一个时间,过了这个时间,该cookie就失效了。或者是用max-age指定当前cookie是在多长时间之后而失效。如果服务器返回的一个cookie,没有指定其expire time,那么表明此cookie有效期只是当前的session,即是session cookie,当前session会话结束后,就过期了。对应的,当关闭(浏览器中)该页面的时候,此cookie就应该被浏览器所删除了。
l secure:表示该cookie只能用https传输。一般用于包含认证信息的cookie,要求传输此cookie的时候,必须用https传输。
l httponly:表示此cookie必须用于http或https传输。这意味着,浏览器脚本,比如javascript中,是不允许访问操作此cookie的。
Cookie的缺陷
l cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
l 由于在HTTP请求中的cookie是明文传递的,所以安全性成问题。(除非用HTTPS)
l Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的。