HTTP协议并不是对等的,需要客户端和服务端,通过请求和响应模型实现。
请求报文的结构
- 请求方法
- 请求的URI
- 协议版本
- 可选的请求首部字段
- 内容实体
响应报文的结构
- 协议版本
- 状态码
- 解释状态码的原因短语
- 可选的响应首部字段
- 主体
HTTP是无状态协议
对HTTP来说,每个请求响应都是独立的,不关心请求之间的联系。
HTTP是通过Cookie技术来保存用户状态的。
Cookie
服务器通过Set-Cookie首部字段信息设置一个Cookie值,(服务器自己也会保存这个值)通知客户端要保存这个Cookie值,客户端在下次请求时自动在请求头中加入Cookie值后发送。服务器对比这个Cookie就知道这个那个用户发来的请求了。
方法种类
http 1.0 1.1 都支持的:
- GET
- POST
- PUT
- DELETE
- HEAD:获取报文头
http1.1新增的:
- OPTIONS:查询服务器支持的方法种类, OPTIONS * HTTP/1.1
- TRACE:追踪路径,会引发跨站追踪CST攻击,一般不使用。
- CONNECT:要求使用隧道协议连接代理
仅http1.0支持,也就是被http/1.1淘汰了:
- LINK
- UNLINK
长连接 keep-alive
又叫持久连接,好处是减少了TCP连接和断开的次数。
在http/1.1中默认是长连接了
管线化 pipelining
管线化,就是同时发送多个请求。相当于一个连接中的串行请求响应,变成并行的。
HTTP报文结构
- 报文首部
- 空行
- 报文主体
其中请求报文首部又分为
- 请求行:方法、URI、HTTP版本
- 请求首部
- 通用首部
- 实体首部
响应报文首部又包含:
- 状态行:状态码、原因短语、版本
- 响应首部
- 通用首部
- 实体手部
内容编码
压缩传输
gzip
compress
deflate
identity(不进行编码)
分块传输编码
Chunked Transfer Coding
多部分对象集合
multipart/form-data
multipart/byterabge
boundary=xxx
可以套嵌使用
范围请求
断点重连
Range: bytes=5001-10000
内容协商
Accept
Accept-Charset
Accept-Encoding
Accept-Language
Content-Language
服务器驱动协商
客户端驱动协商
透明协商
状态码
RFC2616定义的状态码40种,WebDAV 扩展了一些状态码
WebDAV(Web-based Distributed Authoring and Versioning, 基于万维网的分布式创作和版本控制),相当于http/1.1的增强版,主要用于操作文件,比如网盘场景。
1xx 信息类,表示正在处理中
2xx 成功
- 200 成功
- 204 No content : 没有内容。不会返回任何实体的主体,浏览器的页面不会发生更新。
- 206 Partial Content : 部分内容。用于范围请求
3xx 重定向
- 301 Moved Permanently : 永久重定向。如果此页面收藏了标签的话,浏览器可能会自动把标签中的地址改为Location中的地址
- 302 Found:临时重定向,可用于页面地址修改后的发布,如果地址写错了可以改过来,可以随时修改。如果用301,用户浏览器的标签可能会保存错误的地址,这时就不太好处理。
- 303 See Other: 与302相似,但是明确要求客户端用Get方法
- 304 Not Modified:与重定向无关。页面不会更新,而是使用浏览器中的缓存。一般会在条件请求的返回中出现。条件请求:If-Modified-Since,If-Unmodified-since, If_Range, If-Match, If-None-Match。
- 307 Temperary Redirect:临时重定向,不会将请求方法改为GET。
4xx 客服端异常
- 400 :请求的报文的语法错误
- 401 Unauthorized:未授权,会同时返回 WWW-Authenticate,浏览器上会弹出认证框
- 403 Forbidden:拒绝访问
- 404 Not Found :资源没找到
5xx 服务端异常
- 500 Internal Server Error : 服务器内部错误
- 501 Service Unavailable : 服务不可用,一般指服务器过载
Web服务器
一个服务器应用部署多个不同域名的应用
一个服务器应用(如一个Tomcat)如何部署多个不同域名的web站点吗,并且端口都是默认端口?
首先DNS肯定要为主机IP绑定两个域名,
当请求进入Tomcat中后如何区分这两个域名呢?通过请求头Host字段的域名来区分,Tomcat的server.xml的<Host>标签需要配置
<Host name="www.111.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="onefolder" debug="0" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="www.222.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="twofolder" debug="0" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
通信数据转发程序
代理
代理:接收请求后转发给其他服务器(不改变请求的URI?)
- 缓存代理
- 透明代理、非透明代理
网关
网关:与代理的功能很相似,也是转发请求。主要区别是网关可以改变请求的URI,使用非http协议请求后续的服务器。
隧道
隧道:在请求端与远距离的服务器建立安全的传输通道。
确认访问用户身份的认证
可以通过哪些特征证明自己呢?
- 我知道密码
- 我有动态令牌
- 我有数字证书
- 我的生物特征认证,人脸、指纹、虹膜
- 我提供我的身份证,或其他证件
HTTP使用的认证方式
- BASIC认证
- DIGEST认证
- SSL客户端认证
- FormBase认证
Windows的统一认证:Kerberos认证、NTLM认证
BASIC认证
原理:
- 客户端发送请求
- 服务端返回 401 Unauthorized; 并附带WWW-Authenticate: Basic realm="请输入用户名和密码"
- 客户端会弹出认证框让用户输入用户名和密码,输入把user:pass进行Base64编码XXX,放到请求头Authorization: Basric XXX,发送给服务端。
- 服务端进行反编码后验证用户名密码,如果验证通过返回200,如果验证失败返回401。
缺点:
用户密码是明文传输,极不安全。
DIGEST认证
原理:不直接传输用户名密码,而是做散列之后进行传输。
- 客户端发送请求
- 发出质询:服务器返回401,响应头WWW-Authenticate: Digest realm="DIGEST", nonce="XXXXX=xxxx",algorithm=MD5, qop="auth"
- 客户端根据质询计算出响应码:Authorization: Digest realm="DIGEST" username="zhangsan", nonce="原nonce",uri="/digest", algorithm=MD5, response="xxxxx", nc=00000001, cnonce="xxxxx"
- 服务端进行验证,返回200或401,成功时返回认证信息Authentication-Info响应头。根据username来查到真实密码,然后进行相同的MD5过程,然后对比是否与请求中的相同来进行判断。
SSL客户端认证
需要客户端安装证书
原理:
- 客户端发请求
- 服务器除了会返回自己的证书外,还会发送Certificate Request报文,要求客户端提供证书
- 客户端发送Client Certificate报文
- 服务端验证通过后,拿到客户端的公钥,用客户端公钥加密响应信息
SSL客户端认证采用双因素认证:加上了表单认证
基于表单的认证
自实现的表单认证方式
Session管理
通过Cookie保存Session_Id, 注意要将此Cookie加上httponly 属性,防止跨站脚本攻击XSS。
Session_Id是与用户密码关联的。
用户密码的保存注意要salt+hash后保存,salt最好随机生成,这样可以保证相同密码的密文密码也是不同的,更难以破解。
HTTP的扩展
1.Ajax: 局部刷新
2.Comet的解决方法
通过延迟应答来模拟服务器推送的功能。
缺点是显而易见的,需要保持连接不断,会消耗更多的资源。
3.SPDY
Google在2010年发布了SPDY,旨在解决HTTP的性能瓶颈,缩短页面加载时间。那么,HTTP有哪些瓶颈呢?
- 一条连接上只能发送一个请求
- 请求只能从客户端开始,没法从服务器进行推送
- 请求的首部太冗长,并且每次都发送相同的首部
SPDY的目标
修改HTTP协议本身!
SPDY没有完全改写HTTP,而是在HTTP和SSL之间加入了一层SPDY层,可以称为会话层。
主要的功能:
- 多路复用:用一条TCP连接并发处理多个HTTP请求。HTTP连接也是一个吧?
- 赋予请求优先级:在并发请求时,为每个请求分配优先级。
- 压缩HTTP首部
- 推送功能
- 服务器提示功能:主动提示客户端来请求所需的资源。
SPDY的问题
需要浏览器和Web服务器做出相应的调整。
SPDY只是将单个域名的通信进行了多路复用,当一个网站上使用多个域名下的资源时,改善效果会打折扣。
4.浏览器的全双工通信的WebSocket
WebSocket 是Web浏览器与Web服务器之间全双工通信标准。
WebSocket也是建立在HTTP基础上的协议,因此连接的发起方任然是客户端,一旦建立连接,就可以双向发送数据了!
特点:
- 推送功能
- 减少了通信量:首部信息很小
过程:
握手-请求:需要添加几个请求头。
- Upgrade: websocket
- Sec-WebSocket-Key: 健值
- Sec-WebSocket-Protocol: 子协议
握手-响应:
- 返回101 Switching Protocols 状态码
- Upgrade: websocket
- Sec-WebSocket-Accept: 由请求中的健值来生成。
通过HTTP建立WebSocket连接之后,不再使用HTTP的数据帧,而是使用WebSocket独立的数据帧!!格式:ws://xxx.com/xxx
WebSocket API
js可以调用此API。
var socket = new WebSocket('ws://example.com:8080/updates');
socket.onopen = function(){
setInterval(function(){
if(socket.bufferedAmount == 0){
socket.send(getUpdateData());
}
});
}
5.HTTP/2.0
HTTP/2.0的特点
- SPDY
- HTTP Speed + MObility: 有微软公司起草,用于改善移动端通信速度和性能的标准,它建立在SPDY和WebSocket的基础之上
- Network-Friendly HTTP Upgrade: 主要在移动端通信时改善HTTP的性能标准
- 多路复用
- TLS义务化
- 协商
- 客户端拉拽、服务端推送
- 流量控制
- WebSocket
6.Web服务器管理文件的WebDAV
WebDAV是基于万维网的分布式创作和版本控制,用于文件操作,比如网盘。
原理:扩展了HTTP/1.1
增加了一些概念:集合、资源、属性、锁
添加了一些方法Method,与GET/POST同级
- LOCK
- UNLOCK
- MOVE
- COPY
- MKCOL
- PROPPATCH
- PROPFIND
扩展了一些状态码:
- 102 Processing
- 207 Multi-Status
- 422 格式不正确
- 423 Locked
- 507 Insufficient Storage
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。