图解HTTP读书笔记

URI和URL的区别

URI:统一资源标识符

URL:统一资源定位符

第二章:简单HTTP协议

1、应用HTTP协议时,必定一端担任客户端角色,另一端担任服务器端角色,有时候两台计算机的角色可能会互换,但HTTP协议能区分服务器与客户端。

2、请求必定由客户端发出。而服务器端回应。下面是请求报文的组成:

1584951664800.png

响应报文的组成

1584951831703.png

3、HTTP是不保存状态的协议:协议自身不具备保存之前发过的请求或响应的功能。

4、告知服务器意图的HTTP方法

  1. GET:获取资源

    GET方法用来访问已被URI识别的资源。指定的资源经过服务器端解析后返回响应内容。

    例子:

    请求 GET /index.html HTTP/1.1
    Host: www.hackr.jp
    响应 返回 index.html 的页面资源
  2. POST:传输实体主体

    POST是向指定资源提交要被处理的数据。

    例子:

    请求 POST /submit.cgi HTTP/1.1
    Host: www.hackr.jp
    Content-Length: 1560(1560字节的数据)
    响应 返回 submit.cgi 接收数据的处理结果
  3. PUT:传输文件

    由于HTTP/1.1的PUT方法自身不带验证机制,任何人都可以上传文件,存在安全问题,一般Web网站不使用该方法。

  4. HEAD:获得报文首部

    HEAD方法和GET方法一样,只是不返回报文主体部分。一般用于确认URI的有效性和资源更新的日期时间。

  5. DELETE:删除文件

    DELETE方法删除文件,与PUT相反的方法。但由于与PUT方法一样的原因,所以一般不使用。

  6. OPTIONS:询问支持的方法

    OPTIONS方法用来查询针对请求URI指定的资源支持的方法。

    例如:

    请求 OPTIONS * HTTP/1.1
    Host: www.hackr.jp
    响应 HTTP/1.1 200 OK
    Allow: GET, POST, HEAD, OPTIONS(回服务器支持的方法)
  7. TRACE:追踪路径

    TRACE方法是让Web服务器端将之前的请求通信还回给客户端的方法。可以查询发出去的请求是怎么被加工修改的,一般用于Debug。

    TRACE方法不常用,而且容易引发XST(跨站追踪)攻击,通常不会用。

  8. CONNECT:要求用隧道协议连接代理

    CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要用SSL(安全套接层)和TLS(传输层安全)协议吧通信内容加密后经网络隧道传输。

5、持久连接节省通信量

HTTP/1.1中,所有的连接默认都是持久连接。持久连接减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。

持久连接使得多数请求以管线化方式发送成为可能。从前发送请求后需等待并受到响应才能发送下一个请求。管线化技术可以不用等待响应时间就直接发送下一个请求。

6、使用Cookie的状态管理

Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端的状态。

客户端请求服务器后,如果服务器需要记录用户状态,服务器会在响应信息中包含一个Set-Cookie的响应头,客户端会根据这个响应头存储Cookie信息。再次请求服务器时,客户端会在请求信息中包含一个Cookie请求头,而服务器会根据这个请求头进行用户身份、状态等较验。

Cookie实际上是一小段的文本信息(key-value格式)。

请求报文例子(自动发送保存的Cookie信息)

GET /image/ HTTP/1.1

Host: hackr.jp

Cookie: sid=1342077140226724

第三章:HTTP报文内的HTTP信息

1、HTTP报文

用于HTTP协议交互的信息叫做HTTP报文。HTTP报文本身是由多行数据(CR+LF换行)构成的字符串文本,通常不一定有报文主体。

第四章:返回结果的HTTP状态码

1、状态码

状态码就是当客户端向服务器发送请求时,描述返回的请求结果。

类别 原因短语
1XX Informational(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错

第 5 章 与 HTTP 协作的 Web 服务器

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

HTTP/1.1规范允许一台HTTP服务器搭建多个Web站点。就是不同的域名经过DNS服务器解析后IP地址相同。

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

代理

代理是一种有转发功能的应用程序,它接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。

代理不改变请求URI,会直接发送给前方持有资源的目标服务器。在HTTP通信中,可能级联多台代理服务器。请求和响应的转发会经过数台代理服务器,转发时,需要附加Via首部字段以标记出经过的主机信息。

缓存代理:代理转发响应时,缓存代理会预先将资源的副本保存在代理服务器上。当代理再次接收到相同资源的请求时,就可以直接将对应缓存资源作为响应返回。

透明代理:转发请求或响应时,不对报文做任何加工的代理类型叫透明代理。反之,就是非透明代理。

网关

网关的工作机制与代理类似。但网关可以使通信线路上的服务器提供非HTTP协议服务。

image-20200324111112977

隧道

隧道可按要求建立起一条与其他服务器的通信线路,届时使用SSL等加密手段进行通信。隧道的目的是确保客户端与服务器进行安全的通信。隧道本身不会解析HTTP请求。

第六章:HTTP首部

1、HTTP首部字段

使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。

HTTP首部字段分为4种类型:

通用首部字段:请求报文和响应报文都会使用的首部。

请求首部字段:从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。

响应首部字段:从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。

实体首部字段:针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。

2、HTTP/1.1通用首部字段

  • Cache-Control

    通过指定首部字段Cache-Control的指令,可以操作缓存的工作机制。

    指令的参数可选,多个指令间通过,分隔。

    比如:

    Cache-Control: private, max-age=0, no-cache
    

    请求指令列表:

    指令 参数 说明
    no-cache 强制向源服务器再次验证
    no-store 不缓存请求或响应的任何内容
    max-age = [ 秒] 必需 响应的最大Age值
    max-stale( = [ 秒]) 可省略 接收已过期的响应
    min-fresh = [ 秒] 必需 期望在指定时间内的响应仍有效
    no-transform 代理不可更改媒体类型
    only-if-cached 从缓存获取资源
    cache-extension - 新指令标记(token)

    响应指令:

    指令 参数 说明
    public 可向任意方提供响应的缓存
    private 可省略 仅向特定用户返回响应
    no-cache 可省略 缓存前必须先确认其有效性
    no-store 不缓存请求或响应的任何内容
    no-transform 代理不可更改媒体类型
    must-revalidate 可缓存但必须再向源服务器进行确认
    proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
    max-age = [ 秒] 必需 响应的最大Age值
    s-maxage = [ 秒] 必需 公共缓存服务器响应的最大Age值
    cache-extension - 新指令标记(token)
  • Connection

    Connection首部字段有如下两个作用:

    • 控制不再转发给代理的首部字段

      在客户端发送请求和服务器返回响应内,使用Connection首部字段可以控制不再转发给代理的首部字段。

    • 管理持久连接

      HTTP/1.1版本的默认连接都是持久连接。所以客户端会在持久连接上连续发送请求。当服务器端想明确断开连接时,则指定Connection首部字段值为Close。

      HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定 Connection 首部字段的值为 Keep-Alive。

  • Date

    首部字段Date表明创建HTTP报文的日期和时间。

    比如HTTP/1.1 协议使用在 RFC1123 中规定的日期时间的格式如下:

    Date: Tue, 03 Jul 2012 04:40:59 GMT
    
  • Pragma

    Pragma是HTTP/1.1之前版本的遗留字段,仅作为与HTTP/1.1向后兼容而定义。

    规范定义形式唯一:

    Pragma: no-cache
    

    该首部字段属于通用首部字段,但只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。

    所有的中间服务器如果都能以 HTTP/1.1 为基准,那直接采用Cache-Control: no-cache指定缓存的处理方式是最为理想的。但要整体掌握全部中间服务器使用的 HTTP 协议版本却是不现实的。因此,发送的请求会同时含有下面两个首部字段。

    Cache-Control: no-cache
    Pragma: no-cache
    
  • Trailer

    首部字段 Trailer 会事先说明在报文主体后记录了哪些首部字段。该首部字段可应用在 HTTP/1.1 版本分块传输编码时。

    比如:

    HTTP/1.1 200 OK
    Date: Tue, 03 Jul 2012 04:40:56 GMT
    Content-Type: text/html
    ...
    Transfer-Encoding: chunked
    Trailer: Expires
    
    ...(报文主体)...
    0
    Expires: Tue, 28 Sep 2004 23:59:59 GMT
    

    以上用例中,指定首部字段Trailer的值为Expires,在报文主体之后(分块长度0之后)出现了首部字段expires。

  • Transfer-Encoding

    首部字段 Transfer-Encoding 规定了传输报文主体时采用的编码方式。

    HTTP/1.1 的传输编码方式仅对分块传输编码有效。

    比如:

    HTTP/1.1 200 OK
    Date: Tue, 03 Jul 2012 04:40:56 GMT
    Cache-Control: public, max-age=604800
    Content-Type: text/javascript; charset=utf-8
    Expires: Tue, 10 Jul 2012 04:40:56 GMT
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    Content-Encoding: gzip
    Transfer-Encoding: chunked
    Connection: keep-alive
    
    cf0    ←16进制(10进制为3312)
    
    ...3312字节分块数据...
    
    392    ←16进制(10进制为914)
    
    ...914字节分块数据...
    
    0
    

    以上用例中,正如在首部字段 Transfer-Encoding 中指定的那样,有效使用分块传输编码,且分别被分成 3312 字节和 914 字节大小的分块数据。

  • Upgrade

    用于检测HTTP协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。

    image-20200327120533423

    上图,首部字段Upgrade指定值为TLS/1.0。请注意此处两个字段首部字段的对应关系,Connection的值被指定为Upgrade。Upgrade首部字段产生作用的Upgrade对象仅限于客户端和邻接服务器之间。因此,使用首部字段Upgrade时,还需要额外指定Connection:Upgrade

  • Via

    Via是为了追踪客户端和服务器之间的请求和响应报文的传输路径。

    报文经过代理或网关时,会先在首部字段Via中附加该服务器的信息,然后再进行转发。

    Via不仅可用于追踪报文的转发,还可以避免请求回环的发生。所以必须在经过代理时附加该首部字段内容。

    Via首部是为了追踪传输路径,所以经常会和TRACE方法一起使用。

  • Warning

    HTTP/1.1的Warning首部是从HTTP/1.0的响应首部(Retry-After)演变过来的。

    比如:

    Warning: 113 gw.hackr.jp:8080 "Heuristic expiration" Tue, 03 Jul 2012 05:09:44 GMT
    

    格式:

    Warning: [警告码][警告的主机:端口号]“[警告内容]”([日期时间])
    

    HTTP/1.1警告码

    警告码 警告内容 说明
    110 Response is stale(响应已过期) 代理返回已过期的资源
    111 Revalidation failed(再验证失败) 代理再验证资源有效性时失败(服务器无法到达等原因)
    112 Disconnection operation(断开连接操作) 代理与互联网连接被故意切断
    113 Heuristic expiration(试探性过期) 响应的使用期超过24小时(有效缓存的设定时间大于24小时的情况下)
    199 Miscellaneous warning(杂项警告) 任意的警告内容
    214 Transformation applied(使用了转换) 代理对内容编码或媒体类型等执行了某些处理时
    299 Miscellaneous persistent warning(持久杂项警告) 任意的警告内容

3、请求首部字段

  • Accept

    Accept首部字段可通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可使用type/subtype这种形式,一次指定多种媒体类型。

    q是权重系数,范围 0 =< q <= 1,q 值越大,请求越倾向于获得其“;”之前的类型表示的内容,若没有指定 q 值,则默认为1,若被赋值为0,则用于提醒服务器哪些是浏览器不接受的内容类型。

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    

    这个是text/html和application/xhtml+xml优先,然后是application/xml,然后是*/*。

    媒体类型:

    • 文本文件

      text/html, text/plain, text/css ...

      application/xhtml+xml, application/xml ...

    • 图片文件

      image/jpeg, image/gif, image/png ...

    • 视频文件

      video/mpeg, video/quicktime ...

    • 应用程序使用的二进制文件

      application/octet-stream, application/zip

  • Accept——Charset

    Accept-Charset首部字段可用来通知服务器用户代理支持的字符集及字符集的相对优先顺序。另外,可一次性指定多种字符集。与首部字段Accept相同的是可用权重 q 值来表示相对优先级。

    Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
    
  • Accept-Encoding

    用来告知服务器用户代理支持的内容编码及优先级。

    Accept-Encoding: gzip, deflate
    

    几种内容编码

    • gzip

      由文件压缩程序 gzip(GNU zip)生成的编码格式(RFC1952),采用 Lempel-Ziv 算法(LZ77)及 32 位循环冗余校验(Cyclic Redundancy Check,通称 CRC)。

    • compress

      由 UNIX 文件压缩程序 compress 生成的编码格式,采用 Lempel-Ziv-Welch 算法(LZW)。

    • deflate

      组合使用 zlib 格式(RFC1950)及由 deflate 压缩算法(RFC1951)生成的编码格式。

    • identity

      不执行压缩或不会变化的默认编码格式。

    采用权重 q 值来表示相对优先级,这点与首部字段 Accept 相同。另外,也可使用星号(*)作为通配符,指定任意的编码格式。

  • Accept-Language

    告知服务器用户代理能够处理的自然语言集及其优先级。

    Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3
    
  • Authorization

    首部字段 Authorization 是用来告知服务器,用户代理的认证信息(证书值)。通常,想要通过服务器认证的用户代理会在接收到返回的 401 状态码响应后,把首部字段 Authorization 加入请求中。共用缓存在接收到含有 Authorization 首部字段的请求时的操作处理会略有差异。

    Authorization: Basic dWVub3NlbjpwYXNzd29yZA==
    
  • Expect

    客户端使用首部字段 Expect 来告知服务器,期望出现的某种特定行为。因服务器无法理解客户端的期望作出回应而发生错误时,会返回状态码 417 Expectation Failed。

  • From

    用来告知服务器使用用户代理的用户电子邮件地址。通常的目的是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。

  • Host

    首部字段 Host 会告知服务器,请求的资源所处的互联网主机名和端口号。Host 首部字段在 HTTP/1.1 规范内是唯一一个必须被包含在请求内的首部字段。

    请求被发送至服务器时,请求中的主机名会用 IP 地址直接替换解决。但如果这时,相同的 IP 地址下部署运行着多个域名,那么服务器就会无法理解究竟是哪个域名对应的请求。因此,就需要使用首部字段 Host 来明确指出请求的主机名。若服务器未设定主机名,那直接发送一个空值即可。

  • If-Match

    格式如If-xxx这样的请求首部字段,都可以称之为条件请求,服务器收到请求,只有判定条件为真时,才会执行请求。

    服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。

    还可以使用(*)指定If-Match的字段值,这种情况下服务器将忽略ETag值,只要资源存在就处理请求

    If-Match: "123456"
    
  • If-Modified-Since

    它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源都没有过更新,则返回状态码 304 Not Modified 的响应。

    用于确认代理或者客户端拥有的本地资源的有消息。

    If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT
    
  • If-None-Match

    条件请求,和If-Match作用相反。当该字段值的实体标记(ETag)值与请求资源的ETag不一致时,告知服务器处理该请求

  • If-Range

    首部字段 If-Range 属于附带条件之一。它告知服务器若指定的 If-Range 字段值(ETag 值或者时间)和请求资源的 ETag 值或时间相一致时,则作为范围请求处理。反之,则返回全体资源。

  • If-Unmodified-Since

    首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服务器,指定的请求资源只有在字段值内指定的日期时间之后,未发生更新的情况下,才能处理请求。如果在指定日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应返回。

  • Max-Forwards

    通过 TRACE 方法或 OPTIONS 方法,发送包含首部字段 Max-Forwards 的请求时,该字段以十进制整数形式指定可经过的服务器最大数目。服务器在往下一个服务器转发请求之前,Max-Forwards 的值减 1 。当服务器接收到 Max-Forwards 值为 0 的请求时,则不再进行转发,而是直接返回响应。

    可以防止由于未知原因导致的请求陷入循环。

  • Proxy-Authorization

    接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段 Proxy-Authorization 的请求,以告知服务器认证所需要的信息。

    Proxy-Authorization: Basic dGlwOjkpNLAGfFY5
    
  • Range

    Range: bytes=5001-10000
    

    对于只需获取部分资源的范围请求,包含首部字段 Range 即可告知服务器资源的指定范围。上面的示例表示请求获取从第 5001 字节至第 10000 字节的资源。

  • Referer

    首部字段 Referer 会告知服务器请求的原始资源的 URI。

    Referer: http://www.hackr.jp/index.htm
    
  • TE

    TE会告知服务器客户端能够处理响应的传输编码方式及相对优先级。它和首部字段Accept-Encoding的功能很相像,但是用于传输编码。

    TE: gzip, deflate;q=0.5
    
  • User-Agent

    首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传达给服务器。

    由网络爬虫发起请求时,有可能会在字段内添加爬虫作者的电子邮件地址。此外,如果请求经过代理,那么中间也很可能被添加上代理服务器的名称。

    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1
    

4、响应首部字段

  • Accept-Ranges

    用来告知客户端服务器是否能处理范围请求。

    可指定的字段值有两种,可处理范围请求时指定其为 bytes,反之则指定其为 none。

    Accept-Ranges: bytes
    
  • Age

    告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。

    若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段 Age。

    Age: 600
    
  • ETag

    ETag能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应ETag值。

    另外,当资源更新时,ETag也需要更新。生成ETag时,并没有统一的算法规则,而仅仅由服务器分配。

    强ETag和弱ETag:

    强 ETag 值,不论实体发生多么细微的变化都会改变其值。

    弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。

    ETag: "82e22293907ce725faf67773957acd12"
    
  • Location

    使用Location可以将响应接收方引导至某个与请求URI位置不同的资源。

    基本上该字段会配合3xx: Redirecton的响应,提供重定向的URI。

    Location: http://www.usagidesign.jp/sample.html
    
  • Proxy-Authenticate

    把代理服务器所要求的认证信息发送给客户端。

    Proxy-Authenticate: Basic realm="Usagidesign Auth"
    
  • Retry-After

    告知客户端应该在多久之后再次发送请求。主要配合状态码 503 Service Unavailable 响应,或 3xx Redirect 响应一起使用。

    字段值可以指定为具体的日期时间(Wed, 04 Jul 2012 06:34:24 GMT 等格式),也可以是创建响应后的秒数。

  • Server

    告知客户端当前服务器安装的HTTP服务器应用程序的信息。不单单会标出服务器的软件应用名称,还有可能包括版本号和安装时启用的可选项。

    Server: Apache/2.2.6 (Unix) PHP/5.2.5
    
  • Vary

    首部字段 Vary 可对缓存进行控制。源服务器会向代理服务器传达关于本地缓存使用方法的命令。

    从代理服务器接收到源服务器返回包含 Vary 指定项的响应之后,若再要进行缓存,仅对请求中含有相同 Vary 指定首部字段的请求返回缓存。即使对相同资源发起请求,但由于 Vary 指定的首部字段不相同,因此必须要从源服务器重新获取资源。

  • WWW-Authenticate

    用于HTTP访问控制。它会告知客户端适用于访问请求URI所指定资源的认证方案(Basec或是Digest)和带参数提示的质询(challenge)。状态码 401 Unauthorized 响应中,肯定带有首部字段 WWW-Authenticate。

5、实体首部字段

  • Allow

    用于通知客户端能够支持Request-URI指定资源的所有HTTP方法。当服务器接收到不支持的HTTP方法时,会以状态码405 Method Not Allowed作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。

  • Content-Encoding

    告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。

    主要采用4种内容编码方式:gzip、compress、deflate、identity。

  • Content-Language

    告知客户端,实体主体使用的语言。

  • Content-Length

    首部字段 Content-Length 表明了实体主体部分的大小(单位是字节)。

  • Content-Location

    首部字段 Content-Location 给出与报文主体部分相对应的 URI。和首部字段 Location 不同,Content-Location 表示的是报文主体返回资源对应的 URI。

  • Content-MD5

    首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。

    客户端会对接收的报文主体执行相同的 MD5 算法,然后与首部字段 Content-MD5 的字段值比较

    Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==
    
  • Content-Range

    针对范围请求,返回响应时使用的首部字段 Content-Range,能告知客户端作为响应返回的实体的哪个部分符合范围请求。字段值以字节为单位,表示当前发送部分及整个实体大小。

  • Content-Type

    首部字段 Content-Type 说明了实体主体内对象的媒体类型。和首部字段 Accept 一样,字段值用 type/subtype 形式赋值。

    Content-Type: text/html; charset=UTF-8
    
  • Expires

    首部字段 Expires 会将资源失效的日期告知客户端。缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。

    Expires: Wed, 04 Jul 2012 08:26:05 GMT
    
  • Last-Modified

    首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个值就是 Request-URI 指定资源被修改的时间。

    Last-Modified: Wed, 23 May 2012 09:59:55 GMT
    

第七章 确保Web安全的HTTPS

1、HTTP的缺点

  • 通信使用明文,内容可能会被窃听。
  • 不验证通信方的身份,因此有可能遭遇伪装。
  • 无法证明报文的完整性,所以有可能已遭篡改。

2、加密处理防止被窃听

通信的加密

一种方式就是将通信加密。HTTP 协议中没有加密机制,但可以通过和 SSL(Secure Socket Layer,安全套接层)或 TLS(Transport Layer Security,安全层传输协议)的组合使用,加密 HTTP 的通信内容。

用 SSL 建立安全通信线路之后,就可以在这条线路上进行 HTTP 通信了。与 SSL 组合使用的 HTTP 被称为 HTTPS(HTTP Secure,超文本传输安全协议)或 HTTP over SSL。

内容的加密

还有一种将参与通信的内容本身加密的方式。由于 HTTP 协议中没有加密机制,那么就对 HTTP 协议传输的内容本身加密。即把 HTTP 报文里所含的内容进行加密处理。

在这种情况下,客户端需要对 HTTP 报文进行加密处理后再发送请求。

为了做到有效的内容加密,前提是要求客户端和服务器同时具备加密和解密机制。主要应用在 Web 服务中。有一点必须引起注意,由于该方式不同于 SSL 或 TLS 将整个通信线路加密处理,所以内容仍有被篡改的风险。

3、不验证通信方的身份就可能遭遇伪装

HTTP 协议中的请求和响应不会对通信方进行确认。任何人都可以发起请求。

有如下隐患:

  • 无法确定请求发送至目标的 Web 服务器是否是按真实意图返回响应的那台服务器。有可能是已伪装的 Web 服务器。

  • 无法确定响应返回到的客户端是否是按真实意图接收响应的那个客户端。有可能是已伪装的客户端。

  • 无法确定正在通信的对方是否具备访问权限。因为某些 Web 服务器上保存着重要的信息,只想发给特定用户通信的权限。

  • 无法判定请求是来自何方、出自谁手。

  • 即使是无意义的请求也会照单全收。无法阻止海量请求下的 DoS 攻击(Denial of Service,拒绝服务攻击)。

如何解决:

  • 查明对手的证书。虽然使用 HTTP 协议无法确定通信方,但如果使用 SSL 则可以。SSL 不仅提供加密处理,而且还使用了一种被称为证书的手段,可用于确定方。

4、中间人攻击

请求或响应在传输途中,遭攻击者拦截并篡改内容的攻击称为中间人攻击(Man-in-the-Middle attack,MITM)。

如何防止篡改

虽然有使用 HTTP 协议确定报文完整性的方法,但事实上并不便捷、可靠。其中常用的是 MD5 和 SHA-1 等散列值校验的方法,以及用来确认文件的数字签名方法。

提供文件下载服务的 Web 网站也会提供相应的以 PGP(Pretty Good Privacy,完美隐私)创建的数字签名及 MD5 算法生成的散列值。

可惜的是,用这些方法也依然无法百分百保证确认结果正确。因为 PGP 和 MD5 本身被改写的话,用户是没有办法意识到的。

为了有效防止这些弊端,有必要使用 HTTPS。SSL 提供认证和加密处理及摘要功能。

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

HTTPS 并非是应用层的一种新协议。只是 HTTP 通信接口部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)协议代替而已。通常,HTTP 直接和 TCP 通信。当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 通信了。

SSL 是独立于 HTTP 的协议,所以不光是 HTTP 协议,其他运行在应用层的 SMTP 和 Telnet 等协议均可配合 SSL 协议使用。可以说 SSL 是当今世界上应用最为广泛的网络安全技术。

相互交换密钥的公开密钥加密技术

SSL 采用一种叫做公开密钥加密(Public-key cryptography)的加密处理方式。加密和解密同用一个密钥的方式称为共享密钥加密(Common key crypto system),也被叫做对称密钥加密。

公开密钥加密使用一对非对称的密钥。一把叫做私有密钥(private key),另一把叫做公开密钥(public key)。顾名思义,私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。

使用方式:发送密文的一方使用对方的公开密钥进行加密处理, 对方收到被加密的信息后, 再使用自己的私有密钥进行解密。

HTTPS 采用混合加密机制

HTTPS 采用共享密钥加密和公开密钥加密两者并用的混合加密机制。公开密钥加密与共享密钥加密相比,处理速度要慢。所以在确保交换的密钥是安全的前提下,使用共享的密钥加密方式进行通信。

认证

证明公开密钥是正确性的证书
因为公开密钥加密还存在一些问题,无法验证公开密钥本身是货真价实的公开密钥。
为了解决这个问题,可以使用由数字证书机构(CA)和其相关机构颁发的公开密钥证书。

  1. 第三方机构会对公开密钥进行数字签名,并将这个已签名的公开密钥放入到公钥证书(可以叫数字证书或证书)中绑定在一起。

  2. 服务器会将这份公钥证书发送到客户端。

  3. 客户端对公钥证书进行校验。
    校验通过,客户端就会明白两件事:1.认证服务器的公开密钥是真实有效的数字证书认证机构。2.服务器的公开密钥是值得信赖的。

6、HTTPS的安全通信机制

img

步骤 1: 客户端通过发送 Client Hello 报文开始 SSL 通信。报文中包含客户端支持的 SSL 的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)。

步骤 2: 服务器可进行 SSL 通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL 版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。

步骤 3: 之后服务器发送 Certificate 报文。报文中包含公开密钥证书。

步骤 4: 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的 SSL 握手协商部分结束。

步骤 5: SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret 的随机密码串。该报文已用步骤 3 中的公开密钥进行加密。

步骤 6: 接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密。

步骤 7: 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准。

步骤 8: 服务器同样发送 Change Cipher Spec 报文。

步骤 9: 服务器同样发送 Finished 报文。

步骤 10: 服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完成。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP 请求。

步骤 11: 应用层协议通信,即发送 HTTP 响应。

步骤 12: 最后由客户端断开连接。断开连接时,发送 close_notify 报文。上图做了一些省略,这步之后再发送 TCP FIN 报文来关闭与 TCP 的通信。

下面是对整个流程的图解。图中说明了从仅使用服务器端的公开密钥证书(服务器证书)建立 HTTPS 通信的整个过程。

img

1 CBC 模式(Cipher Block Chaining)又名密码分组链接模式。在此模式下,将前一个明文块加密处理后和下一个明文块做 XOR 运算,使之重叠,然后再对运算结果做加密处理。对第一个明文块做加密时,要么使用前一段密文的最后一块,要么利用外部生成的初始向量(initial vector,IV)。

7、SSL 和 TLS

HTTPS 使用 SSL(Secure Socket Layer) 和 TLS(Transport Layer Security)这两个协议。

SSL 技术最初是由浏览器开发商网景通信公司率先倡导的,开发过 SSL3.0 之前的版本。目前主导权已转移到 IETF(Internet Engineering Task Force,Internet 工程任务组)的手中。

IETF 以 SSL3.0 为基准,后又制定了 TLS1.0、TLS1.1 和 TLS1.2。TSL 是以 SSL 为原型开发的协议,有时会统一称该协议为 SSL。当前主流的版本是 SSL3.0 和 TLS1.0。

由于 SSL1.0 协议在设计之初被发现出了问题,就没有实际投入使用。SSL2.0 也被发现存在问题,所以很多浏览器直接废除了该协议版本。

SSL 速度慢吗

HTTPS 也存在一些问题,那就是当使用 SSL 时,它的处理速度会变慢。

SSL 的慢分两种。一种是指通信慢。另一种是指由于大量消耗 CPU 及内存等资源,导致处理速度变慢。

和使用 HTTP 相比,网络负载可能会变慢 2 到 100 倍。除去和 TCP 连接、发送 HTTP 请求 • 响应以外,还必须进行 SSL 通信,因此整体上处理通信量不可避免会增加。

另一点是 SSL 必须进行加密处理。在服务器和客户端都需要进行加密和解密的运算处理。因此从结果上讲,比起 HTTP 会更多地消耗服务器和客户端的硬件资源,导致负载增强。

第 8 章 确认访问用户身份的认证

1、HTTP 使用的认证方式

  • BASIC 认证(基本认证)

  • DIGEST 认证(摘要认证)

  • SSL 客户端认证

  • FormBase 认证(基于表单认证)

2、BASIC认证

BASIC 认证(基本认证)是从 HTTP/1.0 就定义的认证方式。即便是现在仍有一部分的网站会使用这种认证方式。是 Web 服务器与通信客户端之间进行的认证方式。

在这里插入图片描述

步骤 1: 当请求的资源需要 BASIC 认证时,服务器会随状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含认证的方式(BASIC) 及 Request-URI 安全域字符串(realm)。

步骤 2: 接收到状态码 401 的客户端为了通过 BASIC 认证,需要将用户 ID 及密码发送给服务器。发送的字符串内容是由用户 ID 和密码构成,两者中间以冒号(:)连接后,再经过 Base64 编码处理。

步骤 3: 接收到包含首部字段 Authorization 请求的服务器,会对认证信息的正确性进行验证。如验证通过,则返回一条包含 Request-URI 资源的响应。

BASIC 认证虽然采用 Base64 编码方式,但这不是加密处理。 不需要任何附加信息即可对其解码。在 HTTP 等非加密通信的线路上进行 BASIC 认证的过程中,如果被人窃听,被盗的可能性极高。

另外, 除此之外想再进行一次 BASIC 认证时,一般的浏览器却无法实现认证注销操作, 这也是问题之一。

BASIC 认证使用上不够便捷灵活,且达不到多数 Web 网站期望的安全性等级,因此它并不常用。

3、DIGEST 认证

为弥补 BASIC 认证存在的弱点,从HTTP/1.1起就有了DIGEST认证。DIGEST认证同样使用质询 / 响应的方式(challenge/response),但不会像 BASIC 认证那样直接发送明文密码。

DIGEST 认证的认证步骤

image-20200331112802973

步骤 1: 请求需认证的资源时,服务器会随着状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含质问响应方式认证所需的临时质询码(随机数,nonce)。

步骤 2: 接收到 401 状态码的客户端,返回的响应中包含 DIGEST 认证必须的首部字段 Authorization 信息。

步骤 3: 接收到包含首部字段 Authorization 请求的服务器,会确认认证信息的正确性。认证通过后则返回包含 Request-URI 资源的响应。

DIGEST 认证提供了高于 BASIC 认证的安全等级,但是和 HTTPS 的客户端认证相比仍旧很弱。DIGEST 认证提供防止密码被窃听的保护机制,但并不存在防止用户伪装的保护机制。

DIGEST 认证和 BASIC 认证一样,使用上不那么便捷灵活,且仍达不到多数 Web 网站对高度安全等级的追求标准。因此它的适用范围也有所受限。

4、SSL 客户端认证

从使用用户 ID 和密码的认证方式方面来讲,只要二者的内容正确,即可认证是本人的行为。但如果用户 ID 和密码被盗,就很有可能被第三者冒充。利用 SSL 客户端认证则可以避免该情况的发生。

认证步骤:

步骤 1: 接收到需要认证资源的请求,服务器会发送 Certificate Request 报文,要求客户端提供客户端证书。

步骤 2: 用户选择将发送的客户端证书后,客户端会把客户端证书信息以 Client Certificate 报文方式发送给服务器。

步骤 3: 服务器验证客户端证书验证通过后方可领取证书内客户端的公开密钥,然后开始 HTTPS 加密通信。

5、基于表单认证

基于表单的认证方法并不是在 HTTP 协议中定义的。客户端会向服务器上的 Web 应用程序发送登录信息(Credential),按登录信息的验证结果认证。

第 9 章 基于 HTTP 的功能追加协议

1、HTTP的一些标准会成为HTTP性能上的瓶颈

  • 一条连接上只可发送一个请求。

  • 请求只能从客户端开始,客户端不可以接收除响应以外的指令。

  • 请求/响应首部未经压缩就发送,首部信息越多延迟越大。

  • 发送冗长的手部,每次互相发送相同的首部造成的浪费较多。

  • 可任意选择数据压缩格式,非强制压缩发送。

2、Ajax

Ajax(Asynchronous JavaScript and XML,异步JavaScript与XML技术)是一种有效利用JavaScript和DOM(Document Object Model,文档对象模型)的操作,以达到局部Web页面替换加载的异步通信手段。由于它只更新一部分页面,响应中传输的数据量会因此而减少,这一优点显而易见。

3、Comet的解决方法

Comet会先将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。因此服务器端一旦有更新,就可以立即反馈给客户端。

4、SPDY

Google在2010年发布,其开发目标旨在解决HTTP的性能瓶颈,缩短Web页面的加载时间。SPDY没有完全改写HTTP协议,而是在TCP/IP的应用层与运输层之间通过新加会话层的形式运作。同时考虑到安全性问题,SPDY规定通信中使用SSL。

使用SPDY后,HTTP协议额外获得的功能:

  • 多路复用

    通过单一的TCP连接,可以无限制处理多个HTTP请求。

  • 赋予请求优先级

    可以给请求逐个分配优先级顺序,这样主要是为了在发送多个请求时,解决因带宽低而导致响应变慢的问题。

  • 压缩HTTP首部

    这样通信产生的数据包数量和发送的字节数就更少了。

  • 推送功能

    支持服务器主动向客户端推送数据的功能。

  • 服务器提示功能

    服务器可以主动提示客户端请求所需的资源,由于在客户端发现资源之前就可以获知资源的存在,因此在资源已缓存等情况下,可以避免发送不必要的请求。

5、WebSocket:使用浏览器进行全双工通信。

WebSocket是建立在HTTP基础上的协议,因此连接的发起方仍是客户端,而一旦确立WebSocket通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文。

WebScoket协议的主要特点:

  • 推送功能:支持服务器想客户端推送数据的推送功能。

  • 减少通信量:只要建立起WebSocket连接,就希望一直保持连接状态,和HTTP相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相应减少了。

为了实现WebSocket通信,在HTTP连接建立之后,需要完成一次“握手”(Handshaking)的步骤。

image-20200331145624027

6、WebDAV

WebDAV(Web-based Distributed Authoring and Versioning,基于万维网的分布式创作和版本控制)是一个可对Web服务器上的内容直接进行文件复制、编辑等操作的分布式文件系统,它还具备文件创建者管理、文件编辑过程中禁止其他用户内容覆盖的加锁功能,以及对文件内容修改的版本控制功能。

第 10 章 构建 Web 内容的技术

1、HTML

HTML(HyperText Markup Language,超文本标记语言)是为了发送Web上的超文本(Hypertext)而开发的标记语言。

2、CSS

CSS(Cascading Style Sheet,层叠样式表),可以指定如何展现HTML内的各种元素,属于样式表标准之一。

3、动态HTML

动态HTML是通过调用客户端脚本语言JavaScript,实现对HTML的Web页面的动态改造。利用DOM(Document Object Model,文档对象模型)可指定欲发生动态变化的HTML元素。

4、DOM

DOM是用以操作HTML文档和XML文档的API。使用DOM可以将HTML内的元素当作对象操作,如取出元素内的字符串、改变那个CSS的属性等。使页面的设计发生改变 。

5、RSS

RSS(简易信息聚合,也叫聚合内容)和Atom都是发布新闻或博客日志等更新信息文档的格式的总称。两者都用到了XML。

6、JSON

JSON(JavaScript Object Notation)是一种以JavaScript(ECMAScript)的对象表示法为基础的轻量级数据标记语言。能够处理的数据类型有false、null、true、对象、数组、数字、字符串,这7种类型。

第 11 章 Web 的攻击技术

HTTP不具备必要的安全功能,从整体来看,HTTP就是一个通用的单纯协议机制,安全性比较弱

1、在客户端即可篡改请求

在WEB应用中从浏览器接收到的HTTP请求的全部内容都可以在客户端自由的变更、篡改。因此web引用可能接收到与预期数据不相同的内容;在HTTP请求报文内加载攻击代码就能对web应用发起对web应用的攻击,如下图。

2、攻击模式分类

  • 主动攻击(active attack)

    主要是攻击者通过直接访问web应用把攻击代码传入的攻击模式。由于该模式是针对服务器上的资源进行攻击,因此攻击者需要能够访问那些资源,主动攻击模式中具有代表性的有SQL注入攻击和OS命令注入攻击

  • 被动攻击(passive attack)

    是指利用圈套策略执行攻击代码的攻击模式。在被动攻击过程中,攻击者不直接对目标web应用访问发起攻击。

因输出值转移不完全引发安全漏洞

  • 跨站脚本攻击

    跨站脚本攻击(Cross-Site-Scripting,XSS)是指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击。动态创建的HTML部分可能有隐藏的漏洞,这样攻击者编写脚本陷阱,用户在自己浏览器上运行时,一不小心就会受到被动攻击。该种攻击方式可能造成以下影响:

  • 利用虚假输入表单骗取用户个人信息

    利用脚本窃取cookie值,被害者在不知情的情况下,帮助攻击者发送恶意请求

  • 显示伪造的文章或者图片

3、SQL注入攻击

SQL注入是指针对Web应用使用的数据库,通过运行非法的SQL而产生的攻击。该安全隐患可能会导致个人信息及机密信息的泄露。由于We应用通常会使用到数据库,如果在调用数据库语句方式存在疏漏,就有可能被执行恶意注入

4、OS命令注入攻击

OS命令注释系统是指通过web应用执行非法的操作系统命令达到攻击的目的。可以从wen应用中通过shell来调用操作系统命令,倘若调用shell时存在疏漏就可以执行插入的非法OS命令,通过os注入攻击可以执行os上安装着的各种程序。

5、HTTP首部注入攻击

HTTP首部注入攻击是指攻击者通过响应首部字段内插入换行,添加任意响应首部或主体的一种攻击,属于被动式攻击。向首部主体添加内容的攻击方式称为HTTP响应截断攻击

6、HTTP响应截断攻击

HTTP响应截断攻击是HTTP首部注入攻击的一种,攻击顺序相同但是要将%0D%0A%0D%0A并排插入字符串后发送,利用这两个连续换行就可以做出HTTTP首部与主体分割所需的空行了,这样就能显示伪造的主体,达到攻击的目的。这样的攻击称作HTTP响应截断攻击。

7、邮件首部注入攻击

是指web应用中的邮件发送功能。攻击者通过向邮件首部To或者Subject内任意添加非法内容发起的攻击。

8、目录遍历攻击

对本无意公开的文件目录,通过非法截断其目录路径后,达成访问目的的一种攻击方式。这种攻击又称路径遍历攻击

9、远程文件包含漏洞

指当部分脚本内容需要从其他文件读入时,攻击者利用指定外部服务器的URL充当依赖文件,让脚本读取后,就可以运行任意脚本的一种攻击方式。(主要是PHP存在的安全漏洞)

10、因设置上或设计缺陷引发的安全漏洞
主要是错误设置web服务器或者是由设计上的一些问题引起的安全漏洞。主要包括下面3个方面

  • 强制浏览

    强制浏览安全漏洞是指,从安置在web服务器的公开目录下的文件中,浏览那些原本非自愿公开的文件。强制浏览可以造成诸如泄露顾客的个人信息等重要情报、泄露原本需要具有访问权限的用户才可以查阅的信息内容、泄露未连接到外界的文件

  • 不正确的错误消息处理

    指web应用的错误小心包含对攻击者有用的信息,包括Web应用抛出的错误消息、数据库等系统抛出的错误消息

  • 开放重定向

    指对任意URL作重定向跳转的功能。

11、 因会话管理疏忽引发的安全漏洞
会话管理是用来管理用户状态的必备功能,但是如果在会话管理上有所疏忽,就会导致用户的认证状态被窃取等后果。

  • 会话劫持

    通过某种非法手段获得用户的ID,并非法使用此会话ID伪装成用户,达到攻击的目的。

  • 会话固定攻击

    对以窃取目标会话ID为主动攻击手段劫持而言,会话固定攻击(Session Fixation)攻击会强制用户使用攻击者指定的会话ID,属于被动攻击

  • 跨站点请求伪造

    指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或者设定信息等某些状态更新,属于被动攻击

11.5其他安全漏洞
密码破解攻击

点击劫持:指利用透明按钮或者链接做成陷阱,覆盖在Web页面之上,又称页面伪装。

dos攻击:是一种让运行中的服务呈现停止状态的攻击,又称服务器停止攻击或拒绝服务攻击。Dos攻击对象不仅限于Web网站还包括网络设备及服务器。主要有两种方式DoS:集中利用访问请求造成资源过载,资源用尽的同时实际服务也就呈现停止状态;通过攻击安全漏洞使服务停止。

后门程序:指开发设置的隐藏入口

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349