图 Http-Request 从上图我们已经看到成功抓包到一次 HTTP 请求和响应了,但是我们看到却有很多TCP请求,接下来我们来分析下这些 TCP 请求是做什么的? 我们看到第一次请求协商的结果是WS=256,然后再 ACK 阶段扩展因子生效,调整了窗口大小。 HTTP 请求,接着序号5是对 HTTP 请求的一次接收确认,序号6是响应 HTTP 请求,序号7是对响应请求的确认。 我们分析这图,挥手流程是这样的: 1.客户端发起一个断开请求,进入 FIN-WAIT 状态 2.服务端确认断开请求 3.服务端立即发送一个断开请求,进入 CLOSE-WAIT 状态 4.客户端确认服务端断开请求 ,进入 TIME-WAIT 状态 我们发现上面的流程2和流程3都是由服务端发起的,那么有没有可能合并这两个请求,一次发送给客户端?
第一次请求 第二次请求 强缓存 可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control 来表明规则。 客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。 浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。 反之返回 200 就相当于重新请求了一遍资源并替换旧资源。 第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。 ETag与If-None-Match 由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器检查 ETag
1. get 请求方式与 post 请求方式 get 请求 从服务器获取数据 没有对服务器产生影响 通常都是 get 请求、 请求参数在 url 地址上显示,时间戳就是后面的各种参数 post 请求 向服务器发送数据 会对服务器产生影响 通常都是 post 请求 请求参数不会在 url 上显示 就像百度翻译翻译一样他是一个动态加载数据,有道翻译是 ajax 请求,真正的 URL 在 XHR 里 2 url 发送请求的时候可能会出现问题。 方法就是转成 16 进制 urlencode 传入参数类型:字典 功能:将存入的字典参数编码为 URL 查询字符串,即转换成以 key1=value1&key2=value2 的形式 enquote 对 urllib.request.Request(url,headers=headers) print(req) # <urllib.request.Request object at 0x0000022D35B9BB88> 2
02、TCP、消息分包和协议设计 一次网络请求经过 DNS 解析知道了目的 IP,现在就要发出网络包了。 能一次 recv 到多个消息,也可能一次 recv 到一个半消息或半个消息,都是有可能的,这就是流式协议的特点。有的文章讲的粘包也是这个概念。 1xx:指示信息--表示请求已接收,继续处理 2xx:成功--表示请求已被成功接收、理解、接受 3xx:重定向--要完成请求必须进行更进一步的操作 4xx:客户端错误--请求有语法错误或请求无法实现 5xx 4.1 同步通讯 vs 异步通讯 同步通讯是指在一个连接中,一个请求的应答没回来前,不能发送下一个请求,整个通讯过程是请求1-应答1-请求2-应答2……这种。 Web 模式业务一般有这些特点: 是请求-应答式,即先客户端请求,才会有服务器应答(少数场景可借助 WebSocket 主动推送); 是同步通讯,一个连接里,只有收到应答后才能发下一个请求(HTTP2
DNS域名解析采用的是递归查询的方式,过程是,先去找DNS缓存->缓存找不到就去找根域名服务器->根域名又会去找下一级,这样递归查找之后,找到了,给我们的web浏览器 2.为什么HTTP协议要基于TCP name=XXG&age=23的GET 请求时发送给服务器的数据: [图2] 可以看出请求包含请求行和请求头两部分。 ,继续处理 2xx:成功——表示请求已经被成功接收、理解、接受。 ),这是时候就用上 keep-alive特性了,建立一次HTTP连接,可以请求多个资源,下载资源的顺序就是按照代码里面的顺序,但是由于每个资源大小不一样,而浏览器又是多线程请求请求资源,所以这里显示的顺序并不一定是代码里面的顺序 保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。 自此一次完整的HTTP事务宣告完成.
0x0 先看名词 DispactherServlet:SpringMVC 的心脏,所有的请求从这里进入,也从这里出去 HandlerAdapter:请求处理器 HandlerMapping:请求和处理对象间的映射关系 ,可以理解为 地址 /api 对应 @RequestMapping("/api") doDispatch: SpringMVC 处理请求的方法 ModelAndView:视图响应对象,例如我们Controller 请求进入 DispactherServlet 会被分配给 doDispatch ,所以直接断点 doDispatch 即可 0x01 请求处理器 doDispatch 会匹配相应的 HandlerMapping 组装 ModelAndView 执行视图合并 获取模板文件和语言信息 将 ModelAndView 中的属性全部传递给 FreeMarker 最后一步生成 Html 并响应到浏览器 0x2 静态资源处理 SpringMVC 在视图处理器如果找不到合适的处理器的情况下,就会视该请求为静态资源请求并使用静态资源解析器解析该请求。
但是在整体负载非常低的情况下,发现部分写入请求很大概率会出现超时,预期 100ms 内完成的请求可能耗时超过 1s。 ; 主节点更新副本集 majority 同步进度,并释放之前 hold 住的请求,给用户返回结果。 总体来说,有 2 种出现问题的可能性:单机写数据慢或者主从复制慢。 心跳如何导致写请求卡住 MongoDB 定期(默认2秒)交互一次心跳。考虑下面的情形: T0时刻,用户向副本集写入一条数据,并同步到所有节点。 Secondary2 节点同理; 在切换同步源期间,从节点没有到主上同步新数据。所以新到达主节点的 majority 写入请求会被hold住,触发客户端超时; 副本集触发了新一轮心跳,回归正常。
/plain中的一种)和复杂请求。 而复杂请求发出之前,就会出现一次options请求。 什么是options请求呢? 它是一种探测性的请求,通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。 在ajax中出现options请求,也是一种提前探测的情况,ajax跨域请求时,如果请求的是json,就属于复杂请求,因此需要提前发出一次options请求,用以检查请求是否是可靠安全的,如果options 因此,靠javascript客户端取消options请求是不可能的,只能通过服务端对options请求做出正确的回应,这样才能保证options请求之后,post、put等请求可以被发出。
参考 http://www.iocoder.cn/Tomcat/yuliu/A-request-analysis-2-Socket-is-converted-to-an-internal-request-object / 理解请求信息 请求信息包括以下三条 请求行(request line) 例如GET /images/logo.gif HTTP/1.1,表示从/images目录下请求logo.gif这个文件。 请求头(request header),空行 例如Accept-Language: en 其他消息体 这里以请求行数据的解析为例,在 Http 协议中该行内容格式为: Request-Line = Method AbstractHttp11Processor.process,在此调用getInputBuffer().parseRequestLine(keptAlive)、getInputBuffer().parseHeaders())来解析请求行和请求头部 InternalInputBuffer.parseRequestLine用fill填充缓冲区,然后读取缓冲区来解析请求行。
一个请求进来,到达nginx或者是apache,再到php,直到出现响应,发生了什么事情 ---- PHP的运行模式 1.cli:命令行模式 2.CGI(common gateway interface 每一次请求都是循环往复,所以有些繁琐,这是后面为什么会诞生fastcgi的原因。 3.2.fastcgi自动初始化,创建fastcgi主进程和多个cgi解析器进程,等待来着web服务器的请求(只初始化一次,还有个好处,数据库可以持续化连接)。 当给定的SAPI启动时,PHP进入初始化内核子系统,主要对PHP框架,zend引擎的初始化操作,这个阶段一般是在SAPI启动时执行一次。 worder 进程的生命周期如下图: ---- 第二阶段:请求初始化阶段 当一个请求发生时,在处理请求前需要经历的一个阶段 : Nginx 解析一个请求 当符合php脚本请求的规则的时候,会把这个请求交给反向代理中的
发现有的可以打开,有的无法打开,有的第一次打开很慢,第二次打开很快。 https://www.163.com 4.通过v**访问外部第三方站点: https://v.qq.com,https://api-nusdk.service.boltrend.com/ , 第一次缓慢 除了www.sina.com.cn无法打开外,其他2个站点都可以正常打开。 V**-Server发出code=3,type=4的ICMP差错报文, 差错报文中带上了MTU of next hop【当前设备支持的MTU,见图2】。 路由黑洞,163的服务器协议栈实现了RFC1191 4.通过v**访问外部第三方https://v.qq.com, https://api-nusdk.service.boltrend.com/ , 第一次缓慢
我们看到第一次请求协商的结果是 WS=256,然后再 ACK 阶段扩展因子生效,调整了窗口大小。 HTTP 请求,接着 序号5是对 HTTP 请求的一次接收确认, 序号6是响应 HTTP 请求, 序号7是对响应请求的确认。 客户端发起一个断开请求,进入 FIN-WAIT 状态 2. 服务端确认断开请求 3. 服务端立即发送一个断开请求,进入 CLOSE-WAIT 状态 4. 客户端确认服务端断开请求,进入 TIME-WAIT 状态 我们发现上面的 流程2和 流程3都是由服务端发起的,那么有没有可能合并这两个请求,一次发送给客户端?答案是 可以。 说完 Keep-Alive,我们回到最开始的问题,为啥一次 HTTP 请求会有进行两个端口的握手呢?
Nginx层的HTTP配置如下: 我们看到,在Nginx层,最大支持的HTTP请求body为50m, 而我们这次事故的form请求表单,大约在2M, 远小于限制, 所以:不是Nginx 层HTTP请求 HTTP请求的相关字段被设置后,则会正常发起请求,后台则通过对这些字段的校验,决定此请求是否是合理的跨域请求。 浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 因此,实现CORS通信的关键是服务器(服务器端可判断,让哪些域可以请求)。 整体流程如下: 不合理的跨域请求,我们一般认为是侵略性请求,这一类的请求,我们视为XSS攻击。那么广义而言的XSS攻击又是什么呢? 下面给出2种XSS防御机制。
ajax的跨域请求问题,但是,在这个过程中,我们会发现,在很多post,put,delete等请求之前,会有一次options请求。 而复杂请求发出之前,就会出现一次options请求。 什么是options请求呢? 它是一种探测性的请求,通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。 在ajax中出现options请求,也是一种提前探测的情况,ajax跨域请求时,如果请求的是json,就属于复杂请求,因此需要提前发出一次options请求,用以检查请求是否是可靠安全的,如果options 因此,靠javascript客户端取消options请求是不可能的,只能通过服务端对options请求做出正确的回应,这样才能保证options请求之后,post、put等请求可以被发出。
通过以上步骤我们从TCP/IP模型的角度来理解了一次HTTP请求与响应的过程。 下面这张图更清楚明白: ? 下面具体来看如何进行一步步操作的。 四个基于: 请求与响应:客户端发送请求,服务器端响应数据 无状态的:协议对于事务处理没有记忆能力,客户端第一次与服务器建立连接发送请求时需要进行一系列的安全认证匹配等,因此增加页面等待时间,当客户端向服务器端发送请求 下一次客户端向同样的服务器发送请求时,由于他们之前已经遗忘了彼此,所以需要重新建立连接。 应用层:Http是属于应用层的协议,配合TCP/IP使用。 针对无状态的一些解决策略: 有时需要对用户之前的HTTP通信状态进行保存,比如执行一次登陆操作,在30分钟内所有的请求都不需要再次登陆。于是引入了Cookie技术。 第一次分手:主机1(可以使客户端,也可以是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
第三步: DHCP 请求。这其实是一个选择阶段,客户端主机确认服务器推荐的参数,决定使用,于是依然以广播的形式发送请求向服务器确认。 第四步: DHCP ACK。 这一点算是 DHCP 协议的一个约定了,当某台主机第一次加入某个子网络,它将从 DHCP 服务器获取一个全新的 IP 地址。 B 1 q E 1 y B 2 p E 2 --------- OSPF 是基于链路状态路由选择算法进行实现的,所以它也是一个全局性路由选择算法,算法运行一次即可完成全网的路由信息更新。 假设现在我们的路由器 A 运行 OSPF 协议: 第一次迭代完成后,它得到与 B、E 两台路由器相关的子网络的路径计算。
2. 请求头 每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。 1xx:指示信息——表示请求已经接受,继续处理 2xx:成功——表示请求已经被成功接收、理解、接受。 工作原理图: 从图中我们可以看到原理主要分三步: 第一次请求:浏览器通过http的header报头,附带Expires,Cache-Control,Last-Modified/Etag向服务器请求,此时服务器记录第一次请求的 向服务器请求 服务器根据第一次记录的Last-Modified/Etag和再次请求的If-Modified-Since/Etag做对比,判断是否需要更新,服务器通过这两个头判断本地资源未发生变化,客 户端不需要重新下载 常见流程如下图所示: 与缓存相关的HTTP扩展消息头 Expires:设置页面过期时间,格林威治时间GMT Cache-Control:更细致的控制缓存的内容 Last-Modified:请求对象最后一次的修改时间
多路复用技术 在HTTP/1.x中如果客户端要进行多个并行请求来提高性能,那么必须使用多个TCP连接,这种行为是HTTP/1.x传递模型的直接结果,它确保每个连接一次只能传递一个响应(响应队列),而且这还会导致行首阻塞和底层 HTTP/2,那么攻击者便没有机会引入请求走私所需的模糊性,然而由于HTTP/2降级的普遍但危险的实践,情况往往不是这样 协议降级 HTTP/2降级是使用HTTP/1语法重写HTTP/2请求以生成等效的 x-www-form-urlencoded Content-Length: 25 x=GET / HTTP/1.1 Host: vulnerable-website.com 如果我们简单的构造一下,通过一次发送两个请求 ,这个循环就会重复一次 响应队列中毒后攻击者就可以发送任意请求来捕获另一个用户的响应,当时此时的攻击者并不能控制接收到哪些响应,因为他们总是会收到队列中的下一个响应,即前一个用户请求的响应,在某些情况下这将十分鸡肋 15秒登录一次,到后端的连接每10个请求就重置一次,所以如果进入此状态也不用担心——只需发送几个正常的请求就可以获得一个新的连接 演示过程: Step 1:访问以上链接点击"ACCESS THELAB"
第三步: DHCP 请求。这其实是一个选择阶段,客户端主机确认服务器推荐的参数,决定使用,于是依然以广播的形式发送请求向服务器确认。 第四步: DHCP ACK。 这一点算是 DHCP 协议的一个约定了,当某台主机第一次加入某个子网络,它将从 DHCP 服务器获取一个全新的 IP 地址。 B 1 q E 1 y B 2 p E 2 --------- image OSPF 是基于链路状态路由选择算法进行实现的,所以它也是一个全局性路由选择算法,算法运行一次即可完成全网的路由信息更新。 假设现在我们的路由器 A 运行 OSPF 协议: 第一次迭代完成后,它得到与 B、E 两台路由器相关的子网络的路径计算。
一次完整的http请求处理过程 1、建立连接:接收或拒绝连接请求 2、接收请求:接收客户端请求报文中对某资源的一次请求的过程 3、处理请求:服务器对请求报文进行解析,并获取请求的资源及请求方法等相关信息 HEAD、PUT、DELETE、TRACE、OPTIONS 4、访问资源:服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源 响应报文中通常包括:描述了响应主体MIME类型的Content-Type首部描述了响应主体长度的Content-Length实际报文的主体内容 2)URL重定向:web服务构建的响应并非客户端请求的资源 ,而且一次只处理一个,多个请求被串行响应 多进程I/O模型:并行启动多个进程,每个进程响应一个连接请求 复用I/O结构:启动一个进程,同时响应N个连接请求实现方法:多线程模型和事件驱动多线程模型: 一个进程生成N个线程,每线程响应一个连接请求事件驱动:一个进程处理N个请求 复用的多进程I/O模型:启动M个进程,每个进程响应N个连接请求,同时接收M*N个请求 ?