HTTP篇
前言
HTTP,全称为超文本传输协议,是一种运行在应用层上的协议。
这篇文章主要对HTTP做一个总结,将分为概念、常见状态码、GET和POST的区别、HTTPS与HTTP的区别、在浏览器中输入url并按下回车之后发生了什么等部分。
概念
超文本是指用超链接的方式,将各种不同空间的文字信息组织在一起的网状文本。
所以超文本传输协议是指计算机在两点之间来传输文字、图片、视频等超文本信息的协议。
状态码
- 1XX:表示中间状态码,该请求正在处理。
- 2XX:表示请求处理成功。
- 3XX:表示重定向状态码,需要进行额外操作以完成请求。
- 4XX:客户端状态错误码,服务器无法处理该请求。
- 5XX:服务器错误码,服务器处理请求出错。
2XX 成功
- 200 OK:表示请求处理成功。
- 204 No Content :请求处理成功,但是没有资源需要返回。
- 206 Partical Content:客户端只需要一部分资源,服务器处理成功并且把该资源返回。
3XX 重定向
- 301 Moved Permanently:该状态码表示资源已经分配给了新的URI,如果已经把资源保存为书签了就需要更新书签。
- 302 Found:该状态码表示资源的URI已经临时移动到别的位置,希望用户本次使用临时的URI,但是不会更新书签。
- 303 See Other:表示该资源存在另一个URI,应该使用GET来获取。
- 304 Not Modified:如果客户端使用条件请求,服务器找到了资源但是不能满足条件请求。
- 307 Temporary Redirect:和302相同,但是不允许从POST变为GET。
4XX 客户端错误
- 400 Bad Request:表示报文中存在语法错误。
- 401 Unauthorized:表示需要权限认证。
- 403 Forbidden:表示客户端的访问被拒绝了。
- 404 Not Found:表示服务器上没有请求的资源。
5XX 服务器错误
- 500 Internal Server Error:表示服务器发生错误。
- 502 Bad Gateway:表示作为网关或者代理服务器执行请求的时候从上游服务器接收到无效的响应。
- 503 Service Unavailable:表示服务器正忙。
- 504 Gateway Timeout:作为网关或者代理服务器执行请求的时候未能从上游服务器或者服务器收到响应。
GET和POST的区别
总的来说,GET和POST请求的区别如下:
- GET:用于获取数据,可以被缓存,幂等1,无副作用的。
- POST:用于提交数据,不可以被缓存,非幂等,有副作用的(刷新的时候了浏览器会询问是否重新提交表单)。
GET只能使用ASCII码,POST能使用任意编码吗?
GET请求和POST请求都可以使用URL和body,所以其实是URL只能使用ASCII码。
URL只能使用ASCII码的子集([a-zA-Z0-9$-_.+!*’(),]),空格也是ASCII码但是不能使用在URL上。事实上如果出现了中文字符或者特殊字符可以通过percent encoding将字符转化为URL可用字符。但是这个方式只能把字符转化为可用字符而不会去管字符的字符集编码,所以由于浏览器、操作系统的不同转换出的percent encode可能会不一样导致服务器无法识别。
所以一般在使用的都使用js的Ajax发送请求,不让浏览器插手。
URL的长度有限制吗?
在说GET和POST的区别的时候,有时候会说GET请求由于URL的限制最多只能输入2048个字符。
但是事实上Http协议并没有对GET和POST请求的长度进行限制。这个长度限制主要是由浏览器和服务器进行限制的,为了防止超长URL攻击。
POST请求是分两次发送的吗?
POST请求分为两个部分,请求头和请求体。
有些浏览器会把两个包一起发送,返回200 OK,有些浏览器会分开发送,第一次返回100之后再发送第二个包,返回200 OK(如果遭到服务器拒绝,比如400之类的就不会再发送第二个包)。
GET请求比POST更加安全吗?
一般来说GET请求会把自己参数显示在URL上(事实上要使用body也是可以的),所以比起POST请求显得没有那么安全,但事实上,都是不安全的,因为Http使用的是明文,所以想要安全得用Https。
HTTP和HTTPS的区别
HTTPS是为了解决HTTP的不安全性而在HTTP和TCP之间插入了SSL/TLS协议。
SSL/TLS的流程主要如下:
客户端向服务器发送加密通信请求,请求中包括客户端支持的协议版本和密码套件,一个随机数用于生成会话秘钥。
服务器返回确认信息,以及一个服务器随机数和数字证书。
客户端向CA确认数字证书的有效性,然后取出公钥使用公钥进行加密报文,报文中包括一个随机数,加密方式改变通知(之后会根据3个随机和使用的密码套件来进行加密),客户端握手结束通知。
服务器会返回加密方式变更通知和服务器握手结束通知。
之后双方会采用新的加密方式进行加密通信。
由于SSL层是在TCP层之上的,所以确定加密方式之后还是需要进行三次握手。
HTTP的演变
HTTP1.1
HTTP1.1相比1.0有了如下改进:
- 支持长连接,改善了之前使用重复使用短连接带来的资源消耗。
- 支持管道通信:不需要等第一个请求回来就可以发送第二个请求。
HTTP2
HTTP2相比HTTP1.1有了比较多的改善,具体如下:
- 头部压缩:如果连续几个消息的头部信息是相同的,那么协议会帮你消除重复的部分。这就是HPACK算法,在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
- 二进制格式:把之前的传统文本信息转化为了二进制格式,头信息称为头信息帧,主体信息称为数据帧。
- 数据流:HTTP2中的数据包发送不是连续的,有一个特殊编号来表明是客户端的包还是服务器的包,规定客户端的包为奇数,服务器的为偶数,客户端还可以指定优先级,服务器必须回复优先级比较高的数据包。
- 多路复用:HTTP2中同一个信道可能有多个客户端,
- 服务器推送:提前将资源传给客户端,客户端刚请求HTML的时候就把JS和CSS一起传送给客户端。
在浏览器输入 URL 回车之后发生了什么?
主要流程如下:
- URL解析
- DNS查询
- TCP连接
- 处理请求
- 接受响应
- 渲染页面
以上过程都是在最简单的环境下,没有HTTPS、HTTP2.0、没有代理、最简单的DNS。
URL解析
在输入URL之后,浏览器首先会进行检查输入的是一个URL还是搜索内容,URL是否合法等等。
然后会HSTS会强制客户端使用HTTPS进行通信。
之后有些浏览器会进行安全检查、访问限制等操作。
最后会检查缓存,根据是否有缓存、缓存是否需要更新来显示页面。
DNS查询
在将URL转换为域名的时候,浏览器首先会查看自己的缓存中是否有对应域名,有的话则返回。
如果没有则先看HOST文件中是否存在域名,然后查看操作系统中是否有缓存。
如果还是没有则会向路由器查看是否存在缓存。
如果还是没有则向首选DNS查询。
如果还是没有则向根域名请求域名信息。
如果查询到了根域名,那么则需要进行逐级返回。如果查询的是www.xxx.edu.cn,那么根域名会转发给cn域的一级域名服务器,然后cn再会转发到edu的二级域名服务器,直到找到对应IP为止。
DNS劫持
DNS劫持指的就是在上述过程中的某一步,恶意程序将错误的域名返回给客户端,导致客户端访问的并非是输入URL的域名。
HTTP劫持
HTTP劫持指的是恶意程序在客户端和服务器建立连接之后,拦截了请求,然后提前返回请求。
TCP连接
在这一步中,需要发送的信息会进行层层包装,也会进行我们熟悉的TCP三次握手。
然后最后通过ARP广播自己的信息,如果ARP中的机器根据消息的头部信息中的mac地址查看是否是给自己的消息,是则接收(但是回应是单播的)。
SYN攻击
SYN攻击指的是在TCP三次握手中,大量发送第一个SYN同步包,等到服务器发送ACK包回应的时候则不响应,这样会导致服务器误以为客户端没有收到ACK包,从而一直发送造成资源浪费。
ARP攻击
ARP指的是地址解析协议,每个交换机上都存放着IP地址和MAC地址的映射表。
按照一般情况,当客户端进行广播的时候,普通的机器看到不属于自己的消息会进行丢弃,但是有些恶意的机器也会对这些消息进行回应,并且表示自己就是客户端请求的机器,客户端后会以后到达的消息为准建立连接。从而导致交换机上的IP/MAC地址映射表出错,建立了一个恶意机器到客户端的连接。
服务器处理
服务器收到客户端的请求之后会首先进行验证,查看客户端是否有权限、验证是否配置虚拟主机、虚拟主机是否可以接受这个方法。
然后会查看是否有重定向,如果有的话可能会返回301之类的状态码,然后重新进行上面的HTTP操作。
如果没有重定向,则会进行URL重写,查看这个URL是一个具体的资源还是请求,如果是资源则返回资源,如果是请求则会根据路由分配给对应的方法。
浏览器接受响应
浏览器接收到服务器的消息之后,会先查看状态码,然后做出不同的反应(比如进行重定向)。如果资源进行了压缩,还要先解压。
然后会响应资源做缓存。
最后根据资源的不同媒体类型进行不同的操作。
渲染页面
最后浏览器会进行页面渲染,不同的浏览器有不同的操作,大致过程如下:
首先进行HTML解析,构建出一颗DOM树,从上到下逐行解析,中间还会进行语法纠错,完成之后会通知DOM解析完成。
然后会进行CSS解析,构建出一颗CSS规则树。
然后就是将DOM和CSS这两棵树进行合并。
最后就是加载和执行JS脚本。
认证和授权
认证和授权的区别是什么?
- 认证(Authentication):你是谁?
- 授权(Authorization):你有权限做什么?
Cookie
Cookie存在客户端,一般用来保存用户信息。
Cookie可以运用在如下场景:
- 我们在Cookie中保存已经登录过的用户信息,下次访问网站的时候可以自动填写一些登录信息,然后还可以保存一些用户首选项、主题和其他设置信息。
- 使用Cookie保存Session或者Token,向后端发送请求的时候带上Cookie这样能够获取到Session或者Token。
- Cookie还可以用来记录和分析用户行为。比如用户在某个网页停留了多久等等信息。
如何使用Cookie
在SpringBoot中一般采用如下方式设置和读取Cookie:
@GetMapping("/change-username")
public String setCookie(HttpServletResponse response){
Cookie cookie = new Cookie("username","Jovan");
cookie.setMaxAge(7*24*60*60);
response.addCookie(cookie);
return "Username is changed";
}
@GetMapping("/")
public String readCookie(@CookieValue(value = "username", defaultValue = "Atta")String username){
return "My username is"+username;
}
Session
Session最主要的作用就是通过服务端记录用户的状态。
总的来说就是Cookie存在浏览器,Session存放在服务端。
一般我们会把Session存放在Cookie中返回给用户,这样每次用户访问的时候带上Session,服务器就知道用户的状态了。
Token和JWT
Session信息需要保存一份在服务器端,但是这种方式会带来一定的麻烦,比如我们要保证保存Session信息服务器的可用性,不适合移动端等等。
但是采用Token就可以解决这些问题。
Token的本质就是一段签名的JSON格式的数据。
客户端登录之后,服务器返回一段带签名和其他信息的Token,客户端将其存放在Cookie或者localStorage里面。每次发送Http请求的时候是在Header的Authorizaition字段中带上Token。
后记
这篇文章主要总结了一些有关于HTTP的知识点,并且简单介绍了几个常见的网络攻击方式,但是事实上网络攻击还有很多,比如XSS攻击(通过发布恶意的HTML代码注入到网页中)、CSRF 攻击(获取用户的Cookie,然后假装为用户进行操作)等等。
本文参考文献如下:
面试环节:在浏览器输入 URL 回车之后发生了什么?(超详细版)
硬核!30 张图解 HTTP 常见的面试题
计算机网络:这是一份全面 & 详细 的TCP协议攻略
《图解HTTP》
下一篇文章开始主要总结一些操作系统和设计模式中面试会经常问到的一些问题。
幂等:指多次操作都能得到同一个结果。 ↩︎