HTTP演进
HTTP 1.0(废弃)
- 无状态:不跟踪不记录请求的状态;
- 无连接:每次请求都需要建立连接(不支持长连接);
- 队头阻塞:请求全部同步处理,处理请求后,发送响应,接受到ACK,再处理下一个请求;
- 端口易耗尽:主动断开一方,必须经过2个MSL的TIME_WAIT状态;
- 仅支持文本内容;不支持图片、视频;
HTTP 1.1(使用广泛)
- 默认长连接:增加了Connection,设置为keep-alive保持长连接;默认保持;
- 但是连接利用率低,一个域下一般为6个连接;
- 长连接依赖TCP,TCP建立链接后,双发不主动发送FIN包,保持ESTABLISHED状态;
- 管道化技术:将多个请求通过一个TCP连接发送,但是响应仍要顺序接收,不解决队头阻塞;
- 为了能够并发处理多个资源的响应,在开发层面就出现了很多操作:雪碧图;
- 缓存:允许浏览器缓存响应,在资源无变化的情况下,可以直接使用缓存;缓存有失效时间;
- 断点续传:增加Header
- 支持图片、视频、音频;
HTTP 2.0
- 二进制帧:HTTP2将原来的报文中的Header和Body变为首部帧和数据帧,以二进制的格式传输;
- 流标识符:每个二进制帧都有一个流标识符,可以乱序接收响应,再通过流标识符进行整合;(解决了应用层面的队头阻塞,无法解决TCP的队头阻塞)
- 在二进制帧和流标识符的基础上,HTTP2就可以在同一个HTTP连接中并发处理请求响应,实现:多路复用;
- 头部压缩:使用HPack压缩头部;
- 安全性增强:HTTP2基于HTTPS,加密传输;
- 主动推送:在客户端请求资源时,如发现一些连带的资源会主动推送给客户端,如:css、js等资源;
一次完整HTTP请求
- 域名解析:指定域名请求后,需要将域名解析为服务器的ip地址;
- 如果是浏览器发起的HTTP,会先从浏览器缓存中搜索;其次是操作系统的DNS缓存;然后是hosts文件,最后是递归查询域名服务器;
- 建立TCP连接(三次握手)
- TCP连接建立完成后,构建并发起HTTP请求;
- 服务器接受HTTP请求,路由解析、业务逻辑处理,最后返回响应;
- 客户端接受响应;
- 如果是浏览器请求HTML:浏览器边解析边渲染:DOM渲染、加载资源(CSS、JS)
- 如果是服务器请求,正常拿到响应后处理业务逻辑;
- 断开HTTP连接(HTTP 1.1之后默认保持长连接),以下情况会断开连接:
- 明确指定Connection: close;
- 连接超时,由keep-Alive: timeout=xx指定;
- 客户端或服务器主动关闭请求;
- 网络异常;
- 明确指定
- 执行4次挥手断开HTTP连接;
HTTP Status Code
2xx Success Code: indicate that the request was successfully received and processed.
2xx表明请求已被成功接收并处理
- 200 OK: The standard response for successful requests.
- 201 Created: Signifies that a new resource has been successfully created.
- 204 No Content: Indicates that the server successfully processed the request, but is not returning any content.
3xx Redirection Code: signify that further action needs to be take by the browser in order to fulfill the requests.
300系列提示浏览器需要一些额外操作才能满足请求
- 301 Moved Permanently: The URL of the requested resource has been changed permanently. The new URL is given in the response.
- 永久重定向:原地址切换为新的重定向的地址;并且浏览器记住原地址,再次访问原地址则直接重定向,不会再请求服务端;
- 302 Found: Indicates that the resource is temporarily located at another URL.
- 临时重定向:地址栏保持原地址,仅仅是向重定向的地址请求资源;浏览器不会记住这个操作,后续每次访问原地址,都会向服务端请求一次;
- 304 Not Modified: Informs the client that the cashed version of the response is still valid and can be used.
4xx Client Error Code: 400 series indicate the requests contains bad syntax.
4xx表明请求包含语法错误无法被处理
- 400 Bad Request: The server cannot process the request due to a client error.
- 401 Unauthorized: Authentication is required for the requests to be completed.
- 403 Forbidden: The server understands the request but refuses to authorize it.
- 404 Not Found: The server can not find the resource.
- 429 Too Many Requests: The user has sent too many requests in a given amount of time( rate limiting )
5xx Server Error Code: 500 series indicate that something went wrong on the server.
5xx表示服务端存在问题
- 500 Internal Server Error.
- 501 Not Implemented: The server does not support the functionality required to fulfill the request.
- 503 Service Unavailable: The server is not ready to handle the request, often used the maintenance or overloaded servers.
HTTP会话机制
HTTP是无状态的,每次通信都是独立的(长连接只是省去建立连接的损耗),服务端要知道每次请求的额外状态信息就需要其他机制;
Cookie
Cookie:是服务器发送到客户端存储的一段数据,用于跟踪用户状态;
- Cookie由Key-Value构成,明文存储,公开,可修改;通常存储一些公开信息,用于识别用户身份;
- 服务端在返回HTTP响应前,可以通过Set-cookie来写入Cookie(键值对的方式写入),浏览器后续在相同的域下,会自动携带对应的Cookie;
- Cookie的大小、安全、过期、跨域校验等都由浏览器控制和保证;
- Cookie存储:带有expires保存在磁盘中;不带有expires则临时放在内存;
Cookie的弊端:
- 安全问题:
- 名文存储:如果网站的保持登录功能仅由Cookie实现,Cookie被窃取则可以直接登录;
- CSRF攻击:第三方恶意站点,诱导用户发起A站点请求,可以直接携带A站点的Cookie完成请求,如果A站点没有其他防护,可能攻击成功。因此涉及资金、安全等操作仍然要二次验证;
- 容量有限:Cookie的容量由浏览器支持,通常单个域的Cookie大小限制在4KB。过大的Cookie在用户量大时,对服务器是一种开销。
Session
为了解决Cookie的问题,对应的,需要服务端也维护会话数据,session就是其中一种方案;
- Session机制是需要基于Cookie的,需要浏览器通过Cookie携带sessionId;服务器通过sessionId来识别当前的请求状态;(用户信息等)
- 服务端会在首次登录后,生成SessionId存储在服务端,并且放一份到Cookie中;
- 之后客户端的请求中的Cookie需要携带SessionId,服务端就能在服务端的存储中识别到用户的登录时间、敏感信息等;也就实现了控制用户的登录时长。
Session弊端:
- 服务器存储开销:需要额外的存储开销;DB或缓存;
- 分布式环境共享问题:分布式环境下,用户的请求是被负载均衡后路由到后端服务器,此时服务器要想获取对应的session,就需要将session维护在中心服务中;
- 依赖Cookie:服务端要考虑跨域问题。
Token机制
Token是一种无状态的会话方案;将用户信息签名后,在客户端和服务器间传输以识别身份。token方案只是协议机制,非具体方案,等同于http中加了个Header;JWT(Json Web Token)是Token的一种最主流的解决方案;
- JWT的数据通常会进行签名,防止数据篡改,可将登陆时间放到Token,就可以下线用户;
- Token不依赖浏览器策略,可以跨域、不会自动被浏览器放到请求头(防范CSRF)。
- 服务端无存储压力、无状态;
- 很多开放接口的身份识别,就是使用JWT,定时获取token来执行接口的调用;获取token一般需要key、secret,相当于了账号密码。
弊端:
- 服务端不可控:服务端不维护状态的话,就没办法主动失效token;(可以用版本号方案,每个token携带一个版本号,如果token内的数据变更,则递增版本号,来失效旧Token)
- Token是明文公开的。无法存储敏感信息;
重要的请求头
- HttpOnly:控制Cookie能否被前段JavaScript读取;
- 设置为true时禁止前端 JavaScript 脚本读取或修改该Cookie,可以降低XSS攻击的风险;
- 不能防止XSS攻击,但能防止使用XSS攻击来获取用户Cookie;
- 比如XSS攻击者并不获取Cookie,而是直接在恶意JavaScript中直接请求某些重要接口,也是可以成功的(因此重要接口不能仅依赖Cookie)
- 如果前端一定要通过JS读取Cookie(用户的个性化设置、多窗口共享状态等),但同时又有些Cookie是要设置HttpOnly的,就比较复杂,需要根据path来将Cookie拆分,不同的path使用不同的Cookie。但通常太复杂,一般是建议前端不要将Cookie作为存储介质,而是使用sessionStorage/localStorage、全局状态管理器内存存储;
- 设置为