瀏覽器緩存控制詳解(cookie蝶缀、session丹喻、localStorage、Cache-Control等)

摘要:本文將會詳細(xì)的介紹瀏覽器實現(xiàn)緩存控制的相關(guān)知識翁都,包括cookie碍论、session、localStorage柄慰、Cache-Control鳍悠、Expires、ETag坐搔、Last-Modified等概念藏研。

注:在看本文之前建議可以先看一下網(wǎng)頁中的登錄注冊功能是如何實現(xiàn)的,對前端和后端的數(shù)據(jù)交互有個大概的了解概行。

1蠢挡、cookie是什么 && cookie能干什么

  • 給cookie一個定義吧:

Cookie(復(fù)數(shù)形態(tài)Cookies),中文名稱為“小型文本文件”或“小甜餅”。指某些網(wǎng)站為了辨別用戶身份而儲存在用戶本地終端(Client Side)上的數(shù)據(jù)(通常經(jīng)過加密)业踏。 ——摘自維基禽炬。

  • 如何通俗的解釋:

    1. Cookie 是瀏覽器訪問服務(wù)器后,服務(wù)器傳給瀏覽器的一段數(shù)據(jù)勤家。
    2. 瀏覽器需要保存這段數(shù)據(jù)腹尖,不得輕易刪除。
    3. 此后每次瀏覽器訪問該服務(wù)器,都必須帶上這段數(shù)據(jù)惕艳。
  • 所以就能得出cookie的特點:

    1. 服務(wù)器通過設(shè)置Set-Cookie 響應(yīng)頭來設(shè)置 cookie
    2. 瀏覽器得到 cookie 后蛉谜,每次同源的請求的請求頭都會帶上 cookie
    3. 服務(wù)器讀取 cookie 就知道了登錄用戶的信息(如賬戶名等)
    4. cookie 實際上存儲在本地計算機(jī)的硬盤里
    5. cookie 的最大儲存量一般只有4K
  • 那么cookie有哪些缺點呢:

    1. Cookie很容易被用戶篡改( Session 可以解決這個問題,防止用戶篡改)
    2. Cookie 的默認(rèn)有效期理論上在用戶關(guān)閉頁面后就失效断凶,實際上在在20分鐘左右,不同瀏覽器策略不同巫俺。但是后端可以強(qiáng)制設(shè)置有效期(如何設(shè)置見下文)认烁。
    3. Cookie 也有一定的同源策略,不過跟 AJAX 的同源策略稍微有些不同介汹。如:
      • 當(dāng)請求 qq.com 下的資源時却嗡,瀏覽器會默認(rèn)帶上 qq.com 對應(yīng)的 Cookie,不會帶上 baidu.com 對應(yīng)的 Cookie
      • 當(dāng)請求 v.qq.com 下的資源時嘹承,瀏覽器不僅會帶上 v.qq.com 的Cookie窗价,還會帶上 qq.com 的 Cookie
      • 另外 Cookie 還可以根據(jù)路徑做限制,請自行了解叹卷,這個功能用得比較少撼港。
  • 有了Cookie,我們就可以實現(xiàn)這兩件事 :

    • 第一個作用是識別用戶身份骤竹。如:
      比如用戶 A 用瀏覽器訪問了http://a.com帝牡,那么http://a.com 的服務(wù)器就會立刻給 A 返回一段數(shù)據(jù)「uid=1」(這就是 Cookie)。當(dāng) A 再次訪問 http://a.com的其他頁面時蒙揣,就會附帶上「uid=1」這段數(shù)據(jù)靶溜。這樣服務(wù)端就知道 A 是誰了。

    • 第二個作用是記錄歷史懒震。如:
      假設(shè) http://a.com 是一個購物網(wǎng)站罩息,當(dāng) A 在上面將商品 B1 、B2 加入購物車時个扰,JS 可以改寫 Cookie瓷炮,改為「uid=1; cart=B1,B2」,表示購物車?yán)镉?B1 和 B2 兩樣商品了递宅。這樣一來娘香,當(dāng)用戶關(guān)閉網(wǎng)頁冬筒,過三天再打開網(wǎng)頁的時候,依然可以看到 B1 茅主、B2躺在購物車?yán)镂杼担驗闉g覽器并不會無緣無故地刪除這個 Cookie。

    • (需要注意的是:上面的例子只是為了讓大家了解 Cookie 的作用而構(gòu)想出來的诀姚,實際的網(wǎng)站使用 Cookie 時會更謹(jǐn)慎一些响牛。為什么要非常謹(jǐn)慎的使用cookie請從下文尋找答案。)

  • 那么我們?nèi)绾卧O(shè)置cookie呢:
    其實只要一句話:在響應(yīng)頭中設(shè)置Set-Cookie即可赫段,詳見Set-Cookie MDN 呀打。具體參數(shù)如下:

    • Set-Cookie: <cookie-name>=<cookie-value>
      普通的cookie,所有參數(shù)默認(rèn)
    • Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
      cookie 的最長有效時間糯笙,形式為符合 HTTP-date 規(guī)范的時間戳贬丛。
    • Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
      在 cookie 失效之前需要經(jīng)過的秒數(shù)。一位或多位非零(1-9)數(shù)字给涕。假如二者 (指 Expires 和Max-Age) 均存在豺憔,那么 Max-Age 優(yōu)先級更高。
    • Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
      指定 cookie 可以送達(dá)的主機(jī)名够庙。假如沒有指定恭应,那么默認(rèn)值為當(dāng)前文檔訪問地址中的主機(jī)部分(但是不包含子域名)。與之前的規(guī)范不同的是耘眨,域名之前的點號會被忽略昼榛。假如指定了域名,那么相當(dāng)于各個子域名也包含在內(nèi)了剔难。
    • Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
      指定一個 URL 路徑胆屿,這個路徑必須出現(xiàn)在要請求的資源的路徑中才可以發(fā)送 Cookie 首部。
    • Set-Cookie: <cookie-name>=<cookie-value>; Secure
      一個帶有安全屬性的 cookie 只有在請求使用SSL和HTTPS協(xié)議的時候才會被發(fā)送到服務(wù)器偶宫。(注意:非安全站點(http:)已經(jīng)不能再在 cookie 中設(shè)置 secure 指令了)
    • Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
      設(shè)置了 HttpOnly 屬性的 cookie 不能使用 JavaScript 經(jīng)由 Document.cookie 屬性非迹、XMLHttpRequestRequestAPIs 進(jìn)行訪問,以防范跨站腳本攻擊(XSS)读宙。
    • Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
    • Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
      上面兩個允許服務(wù)器設(shè)定一則 cookie 不隨著跨域請求一起發(fā)送彻秆,這樣可以在一定程度上防范跨站請求偽造攻擊(CSRF)楔绞。
  • 如何刪除cookie
    通過設(shè)置cookie的有效期在當(dāng)前時間之前结闸,就可以刪除cookie啦

     var delete_cookie = function(name) {
         document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT;';
     };
    
  • cookie 的 HttpOnly 屬性
    為避免跨域腳本 (XSS)攻擊,通過JavaScript的 Document.cookie API無法訪問帶有 HttpOnly 標(biāo)記的Cookie酒朵,它們只應(yīng)該發(fā)送給服務(wù)端桦锄。如果包含服務(wù)端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調(diào)用,那么就應(yīng)該為其設(shè)置 HttpOnly 標(biāo)記蔫耽。

    Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
    

2结耀、使用session保存信息

  • 先舉個例子看如何使用session
    之前的寫法:直接將數(shù)據(jù)放到cookie里面:
    response.setHeader('Set-Cookie', `login_email=${email}`)
    
    這樣寫一來會暴露用戶的個人信息留夜,二來用戶可以直接通過瀏覽器修改cookie,極有可能獲取到別人的用戶信息图甜,極不安全碍粥。因此出現(xiàn)了下面的使用session的操作:
    let sessions = {}
    let sessionId = Math.random() * 10000 // 設(shè)置sessionId 為一個隨機(jī)數(shù)
    sessions[sessionId] = {login_email:email} // 將email 存儲在sessions這個對象中
    response.setHeader('Set-Cookie', `sessionId = ${sessionId}`) 
    // cookie中存儲的是 sessionId 這個隨機(jī)數(shù)
    
    首先來解釋一下上面的代碼:即設(shè)置cookie的中存儲的值為一個隨機(jī)數(shù),當(dāng)后臺獲取到cookie時黑毅,就可以獲取到該隨機(jī)數(shù)并在sessions這個對象中查找key為這個隨機(jī)數(shù)的value嚼摩,即可知道用戶的郵箱是什么 。如圖所示矿瘦,此時的響應(yīng)頭是這樣的:
  • 那么究竟如何定義session呢:
    首先我們得知道session的本質(zhì):就是存儲在服務(wù)器上的一個哈希表枕面。

    1. sessionID(隨機(jī)數(shù)) 通過 Cookie 發(fā)給客戶端
    2. 客戶端訪問服務(wù)器時,服務(wù)器讀取 sessionID
    3. 服務(wù)器有一塊內(nèi)存(哈希表)保存了所有 session
    4. 通過sessionID 后臺可以得到對應(yīng)用戶的隱私信息缚去,如 id潮秘,email
    5. 這塊內(nèi)存(哈希表)就是服務(wù)器上的所有 session
  • 那么session相對于cookie就沒有缺點了嗎?
    很明顯易结,答案是否定的枕荞。session最大的缺點就是占內(nèi)存,如果你的用戶量非常大搞动,服務(wù)器就需要足夠的容量來存儲數(shù)據(jù)买猖。

  • 不基于cookie能否實現(xiàn)session呢
    答案是肯定的,可以通過設(shè)置網(wǎng)址的查詢參數(shù) + localStorage 來達(dá)成目的滋尉。具體過程如下:

    1. 后端待用戶登陸后設(shè)置他的sessionID玉控,但不把它放在 cookie 里,而是將信息通過響應(yīng)體傳JSON給前端狮惜。
    2. 前端拿到響應(yīng)體中的JSON后將其轉(zhuǎn)換成對象(JSON.parse
    3. 將從JSON中獲取到的數(shù)據(jù)(如 sessionID)放在 localStorage 里面(localStorage里的數(shù)據(jù)目前暫時用不到)
    4. 以后跳轉(zhuǎn)到其他頁面(如首頁)時高诺,將 sessionID 放在 URL 的查詢參數(shù)里(如:window.location.href = '/?sessionId=object.sessionId'
    5. 那么進(jìn)入首頁后,該頁面的 URL 的查詢參數(shù)就帶上了你的sessionID
    6. 后端通過在用戶訪問首頁時碾篡,傳到服務(wù)器的 URL 虱而,來獲取到查詢參數(shù),從而獲取到用戶的 sessionID开泽,然后在數(shù)據(jù)庫中查到sessionID對應(yīng)的信息就可以知道用戶是誰牡拇。

3、localStorage是什么 & localStorage 怎么用

localStorage 是HTML5 技術(shù)提供的api 穆律,是window對象下的一個方法(window.localStorage)惠呼。

localStorage 的實質(zhì)是一個存儲在計算機(jī)本地的哈希表

  • localStorage常用的api

    • localStorage.setItem('myCat', 'Tom')
      訪問當(dāng)前域名下的本地 Storage 對象峦耘,并增加了一個數(shù)據(jù)項通過使用Storage.setItem() 作為 Storage 接口的方法剔蹋,接受一個鍵名和值作為參數(shù),將會把鍵名添加到存儲中辅髓,如果鍵名已存在泣崩,則更新其對應(yīng)的值少梁。
    • let cat = localStorage.getItem('myCat')
      該語法用于讀取 localStorage 項
    • localStorage.removeItem('myCat')
      該語法用于移除 localStorage 項
    • localStorage.clear()
      該語法用于移除所有的 localStorage 項
  • 需要注意的是:localStorage 只能存 string,所以如果想存Object矫付,就需要用JSON來存凯沪,舉個例子:
    localStorage.setItem('jsonObj',JSON.stringify({name:'obj'}))
    然后如果想要解析這個 JSON 將其轉(zhuǎn)換成對象可以使用 JSON.parse()

  • 那么localStorage怎么使用呢:

    • 首先我們需要知道JS中的變量有這樣的問題:變量只在當(dāng)前的會話期內(nèi)有效。即只要刷新頁面买优,之前存儲的變量就被回收了著洼。那么我們?nèi)绾巫屩八鎯Φ淖兞吭谒⑿马撁嬷筮€存在呢,所以就有了localStorage 來解決這個需求而叼。
    • 來看一個小demo身笤,這個demo通過使用 localStorage 完成了變量的持久化存儲,因為localStorage實際上是存儲在本地計算機(jī)中的葵陵,不會因為頁面刷新就導(dǎo)致變量被回收液荸。
      let a = localStorage.getItem('a')
      if(!a){
        a = 0
      }esle{
        a = parseInt(a,10) + 1 // 如果不進(jìn)行轉(zhuǎn)換,將會變成字符串的相加
      }
      console.log(a)
      localStorage.setItem('a',a)
      // 每次刷新頁面 脱篙,a 的值都會加 1
      
    • 常見的使用情景:用戶第一次進(jìn)入頁面時提示用戶一些信息娇钱,第二次進(jìn)入以后就不再提示。 示例代碼如下:
      let already = localStorage.getItem('isPrompt')
      if(!already){
        alert('我們的頁面改版啦')
        localStorage.setItem('isPrompt', true)
      }esle{
         // 已經(jīng)提示了就什么也不做
      }
      
  • localStorage的特點

    1. localStorage 與 HTTP 無關(guān)
    2. HTTP 不會帶上 localStorage 的值
    3. 只有相同域名的頁面才能互相讀取 localStorage(遵循同源策略)
    4. 每個域名 localStorage 最大存儲量為 5Mb 左右(每個瀏覽器不一樣)
    5. 常用場景:記錄有沒有提示過用戶(記錄一些不敏感的信息)
    6. localStorage 理論上永久有效绊困,除非用戶清理緩存文搂,無法設(shè)置過期時間
  • sessionStorage 和 localStorage 有什么關(guān)系和區(qū)別

    • 上一條記錄的 localStorage 的特點,1~4條二者都有秤朗。
    • 區(qū)別:sessionStorage 在用戶關(guān)閉頁面后(即 session 結(jié)束后或者說會話結(jié)束后)就失效煤蹭,而且沒辦法控制;而 localStorage 理論上永久有效取视。
    • sessionStorage 的 api 和 localStorage 完全一樣硝皂。如setItem()getItem()作谭、remove()稽物、clear()

4、關(guān)于上面的概念需要注意的事情

  • cookie 和 session 有什么關(guān)系:
    答:一般來說 cookie 是基于 session 實現(xiàn)的折欠。cookie是存在客戶端本地的贝或,而session是保存在服務(wù)器上的。

  • cookie 和 localStorage 的區(qū)別是什么
    答:cookie 每次請求會被帶給服務(wù)器锐秦,而 localStorage不會咪奖;cookie的最大儲存量一般只有4k,而localStorage 一般有5Mb 农猬;cookie的有效期一般在用戶關(guān)閉頁面后就失效赡艰,而localStorage理論上永久有效

  • 可能你就要問了斤葱,看起來cookie 和 localStorage 幾乎沒有關(guān)系慷垮,為什么要放在一起比較?
    這是由歷史原因的:localStorage 是新API揍堕,在它出現(xiàn)以前料身,之前的前端如何實現(xiàn)跨頁面的數(shù)據(jù)持久化存儲呢?只能通過cookie 衩茸,要知道cookie 和 localStorage 都是存放在計算機(jī)本地芹血,所以當(dāng)時很多程序員都把數(shù)據(jù)放在cookie里,但是有個問題楞慈,你所有存在 cookie里面的東西幔烛,每次請求都會帶到服務(wù)器里面去,如果cookie里面放的東西太多囊蓝,那么每次請求就要花費更多的時間饿悬。所以要達(dá)到跨頁面的數(shù)據(jù)持久化存儲,最優(yōu)解就是使用 localStorage聚霜。

  • 前端永遠(yuǎn)不要讀或者寫cookie狡恬,讀寫cookie一系列的操作是后端需要完成的工作。(這里的前后端指的是代碼上的分離而不是人員上的分離)

5蝎宇、HTTP緩存 & Cache-Control 緩存控制

需要提一句的是:緩存控制其實也是前端性能優(yōu)化的一部分弟劲,所以這一點其實很值得關(guān)注。

緩存控制的使用場景:一些網(wǎng)站需要加載的資源很多姥芥,導(dǎo)致每次刷新頁面速度都非常都慢兔乞,那么該如何加快請求速度,緩存控制就應(yīng)運而生凉唐。

Cache-Control 通用消息頭被用于在http 請求和響應(yīng)中通過指定指令來實現(xiàn)緩存機(jī)制报嵌。緩存指令是單向的, 這意味著在請求設(shè)置的指令,在響應(yīng)中不一定包含相同的指令熊榛。

最常用的響應(yīng)指令:Cache-Control: max-age=<seconds>

  • 設(shè)置緩存存儲的最大周期锚国,超過這個時間緩存被認(rèn)為過期(單位秒)。與Expires相反玄坦,時間是相對于請求的時間血筑。即在設(shè)置的時間內(nèi),請求相同的URL將不會把請求發(fā)送到服務(wù)器煎楣,瀏覽器會阻斷這個請求(即這個請求實際并沒有發(fā)送出去)豺总,然后然后之間展示緩存過的上一次的數(shù)據(jù)(存儲在本地的硬盤或內(nèi)存)。實際開發(fā)中择懂,我們一般設(shè)置為一年31536000秒以上喻喳。
  • 需要注意的是:一般首頁(甚至包括所有的html頁面)不應(yīng)該設(shè)置緩存(chrome瀏覽器甚至?xí)苯咏眠@個設(shè)置,也就是說你給首頁設(shè)置Cache-Control也不會生效)困曙。因為如果你連首頁都設(shè)置了緩存表伦,用戶即使刷新頁面谦去,也不會向服務(wù)器發(fā)送任何請求,那么如果你的代碼更新了蹦哼,用戶在緩存期間將始終無法獲取到最新的版本鳄哭。
  • 實際開發(fā)中的使用:html頁面不設(shè)置Cache-Control,其他資源Cache-Control設(shè)置一年以上纲熏,如果代碼更新(比如js或css)妆丘,該資源的請求的url的查詢參數(shù)加上一個版本號,或者文件名后加隨機(jī)數(shù)即可局劲。也就是說勺拣,只要你的請求的url有一點點不一樣,就不會使用緩存

6鱼填、Expires 是什么 & 有什么不好的地方

  • Expires 也是用來控制緩存的药有,但是現(xiàn)在在開發(fā)中,優(yōu)先使用Cache-Control剔氏。
    Expires 響應(yīng)頭包含日期/時間塑猖, 即在此時候之后,緩存過期谈跛。

  • 如何使用Expires呢:
    設(shè)置響應(yīng)頭羊苟,如:Expires:"Wed, 22 Aug 2018 07:43:17 GMT"
    后面接的是格林尼治時間。當(dāng)過了設(shè)置的時間后緩存就過期了感憾。

  • 所以 ExpiresCache-Control的區(qū)別就是:前者設(shè)置的是什么時候過期蜡励,后者設(shè)置的是過了多久過期。

  • 需要注意的是:如果在 Cache-Control 響應(yīng)頭設(shè)置了 "max-age" 或者 "s-max-age" 指令阻桅,那么 Expires 頭會被忽略凉倚。那么為什么 Cache-Control 優(yōu)先級比Expire 高呢?

  • 因為 Cache-Control 相對于 Expires 是個更新的技術(shù)嫂沉, 而且使用 Expires 是存在bug 的稽寒。

  • Expires 的bug:時間使用的是計算機(jī)本地的時間,如果某一天計算機(jī)時間錯亂趟章,本地時間一直在你設(shè)置的時間之后杏糙,那么他就永遠(yuǎn)使用不了緩存。

7蚓土、ETag 是什么 & MD5 是什么

首先宏侍,Etag 是用來給文件一個版本號的。

那么我們先來了解一下MD5 蜀漆。MD5是一個消息摘要算法谅河。MD5 的常見使用場景:你在網(wǎng)上下載一個很大的文件,下載過程中你怎么知道自己下載的對不對呢?所以MD5 就是為了這種情景而生的绷耍。即網(wǎng)上的文件除了有資源本身外吐限,還會有一個MD5值,然后你下載到本地后的文件也可以算出一個MD5 值锨天,然后二者對比毯盈,如果完全相同則說明下的文件是正確的剃毒。

Etag 的使用場景:

  1. 后端算出資源的MD5值病袄,將其設(shè)置到響應(yīng)頭的Etag里,如:
    Etag:"33a64df551425fcc55e4d42a148795d9f25f89d4"
  2. 然后下一次請求時赘阀,里面這個資源的請求頭就多了一個值:
    If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
  3. 后端就有如下設(shè)置:
    如果請求頭的If-None-Match中的值和資源的MD5一樣益缠,說明資源是最新的,不需要下載基公,即可以返回304狀態(tài)碼( Not Modified)幅慌,然后在此分支下就不用設(shè)置響應(yīng)體了。
  4. 如果MD5的值不一樣轰豆,說明你的資源需要更新胰伍,此時再返回最新的資源作為響應(yīng)體。

Etag 與 Cache-Control 的區(qū)別

  • Cache-Control 直接不會發(fā)請求酸休,只要url一樣骂租,直接使用緩存了的數(shù)據(jù)
  • Etag 則每一次都會請求,只不過如果資源的MD5一樣斑司,就不下載

8渗饮、Last-Modified 是什么 & 使用過程是怎么樣的

Last-Modified 是一個響應(yīng)首部,其中包含源頭服務(wù)器認(rèn)定的資源做出修改的日期及時間宿刮。 它通常被用作一個驗證器來判斷接收到的或者存儲的資源是否彼此一致互站。由于精確度比 ETag 要低,所以這是一個備用機(jī)制僵缺。包含有 If-Modified-SinceIf-Unmodified-Since首部的條件請求會使用這個字段胡桃。

使用過程:

  1. 在瀏覽器第一次請求某一個URL時,服務(wù)器端的返回狀態(tài)會是200磕潮,內(nèi)容是你請求的資源翠胰,同時有一個Last-Modified的屬性標(biāo)記在響應(yīng)頭里,此文件在服務(wù)期端最后被修改的時間揉抵,格式類似這樣:
    Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
  2. 客戶端第二次請求此URL時亡容,根據(jù)HTTP協(xié)議的規(guī)定,瀏覽器會向服務(wù)器傳送If-Modified-Since請求頭冤今,詢問該時間之后文件是否有被修改過:
    If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
  3. 如果服務(wù)器端的資源沒有變化闺兢,則自動返回HTTP 304(NotChanged.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量屋谭。當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時脚囊,則重新發(fā)出資源,返回和第一次請求時類似桐磁。從而保證不向客戶端重復(fù)發(fā)出資源悔耘,也保證當(dāng)服務(wù)器有變化時,客戶端能夠得到最新的資源我擂。

(END)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末衬以,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子校摩,更是在濱河造成了極大的恐慌看峻,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衙吩,死亡現(xiàn)場離奇詭異互妓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坤塞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門冯勉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人摹芙,你說我怎么就攤上這事灼狰。” “怎么了瘫辩?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵伏嗜,是天一觀的道長。 經(jīng)常有香客問我伐厌,道長承绸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任挣轨,我火速辦了婚禮军熏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卷扮。我一直安慰自己荡澎,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布晤锹。 她就那樣靜靜地躺著摩幔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞭铆。 梳的紋絲不亂的頭發(fā)上或衡,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼封断。 笑死斯辰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坡疼。 我是一名探鬼主播彬呻,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柄瑰!你這毒婦竟也來了闸氮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤狱意,失蹤者是張志新(化名)和其女友劉穎湖苞,沒想到半個月后拯欧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體详囤,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年镐作,在試婚紗的時候發(fā)現(xiàn)自己被綠了藏姐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡该贾,死狀恐怖羔杨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杨蛋,我是刑警寧澤兜材,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站逞力,受9級特大地震影響曙寡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寇荧,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一举庶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揩抡,春花似錦户侥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烁设,卻和暖如春替梨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工耙替, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留亚侠,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓俗扇,卻偏偏與公主長得像硝烂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铜幽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容