一文讀懂cookie session token

大家好疏唾,我是前端dog君,一名95后前端小兵函似。2019年畢業(yè)于北京化工大學(xué)槐脏,天津人,不知道有校友和老鄉(xiāng)嘛撇寞?對(duì)前端的熱愛顿天,讓我們?cè)诖讼嗑郏M@篇文章蔑担,能幫助到您牌废,也同時(shí)希望能交到志同道合的小伙伴,共同發(fā)展钟沛,一起進(jìn)步畔规。我的微信號(hào)dm120225,備注簡(jiǎn)書恨统,期待您的光臨叁扫。

最近在公司整理權(quán)限相關(guān)的內(nèi)容三妈,dog君所在公司項(xiàng)目有兩套架構(gòu):一套是前后端未分離,采用的是cookie + session的鑒權(quán)模式莫绣,一套是現(xiàn)有的前后端分離架構(gòu)畴蒲,采用的是token鑒權(quán)模式。正好趁著這個(gè)機(jī)會(huì)復(fù)習(xí)下cookie session 和token之間有什么區(qū)別对室。話不多說模燥,讓我們開始吧!

前言

無狀態(tài)的HTTP協(xié)議

很久很久之前掩宜, Web基本都是文檔的瀏覽而已蔫骂。既然是瀏覽, 作為服務(wù)器牺汤, 不需要記錄在某一段時(shí)間里都瀏覽了什么文檔辽旋, 每次請(qǐng)求都是一個(gè)新的HTTP協(xié)議,就是請(qǐng)求加響應(yīng)檐迟。不用記錄誰剛剛發(fā)了HTTP請(qǐng)求补胚, 每次請(qǐng)求都是全新的。

如何管理會(huì)話

隨著交互式Web應(yīng)用的興起追迟, 像在線購物網(wǎng)站溶其,需要登錄的網(wǎng)站等,馬上面臨一個(gè)問題敦间,就是要管理回話瓶逃,記住那些人登錄過系統(tǒng),哪些人往自己的購物車中放商品每瞒,也就是說我必須把每個(gè)人區(qū)分開金闽。

本文主要講解cookie,session, token 這三種是如何管理會(huì)話的剿骨;

cookie

cookie 是一個(gè)非常具體的東西代芜,指的就是瀏覽器里面能永久存儲(chǔ)的一種數(shù)據(jù)。跟服務(wù)器沒啥關(guān)系浓利,僅僅是瀏覽器實(shí)現(xiàn)的一種數(shù)據(jù)存儲(chǔ)功能挤庇。

cookie由服務(wù)器生成,發(fā)送給瀏覽器贷掖,瀏覽器把cookie以KV形式存儲(chǔ)到某個(gè)目錄下的文本文件中嫡秕,下一次請(qǐng)求同一網(wǎng)站時(shí)會(huì)把該cookie發(fā)送給服務(wù)器。由于cookie是存在客戶端上的苹威,所以瀏覽器加入了一些限制確保cookie不會(huì)被惡意使用昆咽,同時(shí)不會(huì)占據(jù)太多磁盤空間。所以每個(gè)域的cookie數(shù)量是有限制的。

如何設(shè)置

客戶端設(shè)置

document.cookie = "name=xiaoming; age=12 "
  • 客戶端可以設(shè)置cookie的一下選項(xiàng): expires, domain, path, secure(只有在https協(xié)議的網(wǎng)頁中, 客戶端設(shè)置secure類型cookie才能生效), 但無法設(shè)置httpOnly選項(xiàng)

設(shè)置cookie => cookie被自動(dòng)添加到request header中 => 服務(wù)端接收到cookie

服務(wù)端設(shè)置

不管你是請(qǐng)求一個(gè)資源文件(如html/js/css/圖片), 還是發(fā)送一個(gè)ajax請(qǐng)求, 服務(wù)端都會(huì)返回response.而response header中有一項(xiàng)叫set-cookie, 是服務(wù)端專門用來設(shè)置cookie的;

  • 一個(gè)set-cookie只能設(shè)置一個(gè)cookie, 當(dāng)你想設(shè)置多個(gè), 需要添加同樣多的set-cookie
  • 服務(wù)端可以設(shè)置cookie的所有選項(xiàng): expires, domain, path, secure, HttpOnly

Cookie掷酗,SessionStorage调违,LocalStorage

HTML5提供了兩種本地存儲(chǔ)的方式 sessionStorage 和 localStorage;


session

什么是session

session從字面上講泻轰,就是會(huì)話技肩。這個(gè)就類似你和一個(gè)人交談,你怎么知道當(dāng)時(shí)和你交談的是張三而不是李四呢浮声?對(duì)方肯定有某種特征(長相等)表明他是張三虚婿;session也是類似的道理,服務(wù)器要知道當(dāng)前請(qǐng)求發(fā)給自己的是誰泳挥。為了做這種區(qū)分然痊,服務(wù)器就是要給每個(gè)客戶端分配不同的"身份標(biāo)識(shí)",然后客戶端每次向服務(wù)器發(fā)請(qǐng)求的時(shí)候羡洁,都帶上這個(gè)”身份標(biāo)識(shí)“玷过,服務(wù)器就知道這個(gè)請(qǐng)求來自與誰了。至于客戶端怎么保存這個(gè)”身份標(biāo)識(shí)“筑煮,可以有很多方式,對(duì)于瀏覽器客戶端粤蝎,大家都采用cookie的方式真仲。

過程(服務(wù)端session + 客戶端 sessionId)

  • 1.用戶向服務(wù)器發(fā)送用戶名和密碼
  • 2.服務(wù)器驗(yàn)證通過后,在當(dāng)前對(duì)話(session)里面保存相關(guān)數(shù)據(jù),比如用戶角色, 登陸時(shí)間等;
  • 3.服務(wù)器向用戶返回一個(gè)session_id, 寫入用戶的cookie
  • 4.用戶隨后的每一次請(qǐng)求, 都會(huì)通過cookie, 將session_id傳回服務(wù)器
  • 5.服務(wù)端收到session_id, 找到前期保存的數(shù)據(jù), 由此得知用戶的身份

存在的問題

擴(kuò)展性不好

單機(jī)當(dāng)然沒問題, 如果是服務(wù)器集群初澎, 或者是跨域的服務(wù)導(dǎo)向架構(gòu)秸应, 這就要求session數(shù)據(jù)共享,每臺(tái)服務(wù)器都能夠讀取session碑宴。

舉例來說软啼, A網(wǎng)站和B網(wǎng)站是同一家公司的關(guān)聯(lián)服務(wù)。現(xiàn)在要求延柠,用戶只要在其中一個(gè)網(wǎng)站登錄祸挪,再訪問另一個(gè)網(wǎng)站就會(huì)自動(dòng)登錄,請(qǐng)問怎么實(shí)現(xiàn)贞间?這個(gè)問題就是如何實(shí)現(xiàn)單點(diǎn)登錄的問題

  • 1.Nginx ip_hash 策略贿条,服務(wù)端使用 Nginx 代理,每個(gè)請(qǐng)求按訪問 IP 的 hash 分配增热,這樣來自同一 IP 固定訪問一個(gè)后臺(tái)服務(wù)器整以,避免了在服務(wù)器 A 創(chuàng)建 Session,第二次分發(fā)到服務(wù)器 B 的現(xiàn)象峻仇。
  • 2.Session復(fù)制:任何一個(gè)服務(wù)器上的 Session 發(fā)生改變(增刪改)公黑,該節(jié)點(diǎn)會(huì)把這個(gè) Session 的所有內(nèi)容序列化,然后廣播給所有其它節(jié)點(diǎn)。
  • 3.共享Session:將Session Id 集中存儲(chǔ)到一個(gè)地方,所有的機(jī)器都來訪問這個(gè)地方的數(shù)據(jù)。這種方案的優(yōu)點(diǎn)是架構(gòu)清晰溉浙,缺點(diǎn)是工程量比較大萍歉。另外,持久層萬一掛了形用,就會(huì)單點(diǎn)失敗;


另一種方案是服務(wù)器索性不保存session數(shù)據(jù)了蝉绷,所有數(shù)據(jù)就保存在客戶端,每次請(qǐng)求都發(fā)回服務(wù)器枣抱。這種方案就是接下來要介紹的基于Token的驗(yàn)證;

Token

過程

  • 1.用戶通過用戶名和密碼發(fā)送請(qǐng)求
  • 2.程序驗(yàn)證
  • 3.程序返回一個(gè)簽名的token給客戶端
  • 4.客戶端儲(chǔ)存token, 并且每次用每次發(fā)送請(qǐng)求
  • 5.服務(wù)端驗(yàn)證Token并返回?cái)?shù)據(jù)
    這個(gè)方式的技術(shù)其實(shí)很早就已經(jīng)有很多實(shí)現(xiàn)了熔吗,而且還有現(xiàn)成的標(biāo)準(zhǔn)可用,這個(gè)標(biāo)準(zhǔn)就是JWT;

JWT(JSON Web Token)

數(shù)據(jù)結(jié)構(gòu)

實(shí)際的JWT大概就像下面這樣


JSON Web Tokens由dot(.)分隔的三個(gè)部分組成佳晶,它們是:

  • Header(頭部)
  • Payload(負(fù)載)
  • Signature(簽名)
    因此桅狠,JWT通常如下展示:

xxxxx.yyyyy.zzzz

Header(頭部)

Header 是一個(gè) JSON 對(duì)象

{
  "alg": "HS256", // 表示簽名的算法,默認(rèn)是 HMAC SHA256(寫成 HS256)
  "typ": "JWT"  // 表示Token的類型轿秧,JWT 令牌統(tǒng)一寫為JWT
}

Payload(負(fù)載)

Payload 部分也是一個(gè) JSON 對(duì)象中跌,用來存放實(shí)際需要傳遞的數(shù)據(jù)

{
  // 7個(gè)官方字段
  "iss": "a.com", // issuer:簽發(fā)人
  "exp": "1d", // expiration time: 過期時(shí)間
  "sub": "test", // subject: 主題
  "aud": "xxx", // audience: 受眾
  "nbf": "xxx", // Not Before:生效時(shí)間
  "iat": "xxx", // Issued At: 簽發(fā)時(shí)間
  "jti": "1111", // JWT ID:編號(hào)
  // 可以定義私有字段
  "name": "John Doe",
  "admin": true
}

JWT 默認(rèn)是不加密的,任何人都可以讀到菇篡,所以不要把秘密信息放在這個(gè)部分漩符。

Signature(簽名)

Signature 是對(duì)前兩部分的簽名,防止數(shù)據(jù)被篡改驱还。

首先嗜暴,需要指定一個(gè)密鑰(secret)。這個(gè)密鑰只有服務(wù)器才知道议蟆,不能泄露給用戶闷沥。然后,使用Header里面指定的簽名算法(默認(rèn)是 HMAC SHA256)咐容,按照下面的公式產(chǎn)生簽名舆逃。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出簽名后,把 Header疟丙、Payload颖侄、Signature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)"(.)分隔享郊,就可以返回給用戶览祖。

JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature

如何保證安全?

  • 發(fā)送JWT要使用HTTPS炊琉;不使用HTTPS發(fā)送的時(shí)候展蒂,JWT里不要寫入秘密數(shù)據(jù)
  • JWT的payload中要設(shè)置expire時(shí)間

使用方式

客戶端收到服務(wù)器返回的 JWT又活,可以儲(chǔ)存在 Cookie 里面,也可以儲(chǔ)存在 localStorage锰悼。此后柳骄,客戶端每次與服務(wù)端通信,都要帶上這個(gè)JWT箕般。你可以把它放在Cookie里面自動(dòng)發(fā)送耐薯,但是這樣不能跨域,所以更好的做法是放在HTTP請(qǐng)求的頭信息 Authorization 字段里面丝里。

Authorization: Bearer <token>

另一種做法是曲初, 跨域的時(shí)候, JWT就放在POST請(qǐng)求的數(shù)據(jù)體里杯聚。

JWT 的作用

JWT最開始的初衷是為了實(shí)現(xiàn)授權(quán)和身份認(rèn)證作用的臼婆,可以實(shí)現(xiàn)無狀態(tài),分布式的Web應(yīng)用授權(quán)幌绍。大致實(shí)現(xiàn)的流程如下

  • 1.客戶端需要攜帶用戶名/密碼等可證明身份的的內(nèi)容去授權(quán)服務(wù)器獲取JWT信息颁褂;
  • 2.每次服務(wù)都攜帶該Token內(nèi)容與Web服務(wù)器進(jìn)行交互,由業(yè)務(wù)服務(wù)器來驗(yàn)證Token是否是授權(quán)發(fā)放的有效Token傀广,來驗(yàn)證當(dāng)前業(yè)務(wù)是否請(qǐng)求合法颁独。

這里需要注意:不是每次請(qǐng)求都要申請(qǐng)一次Token,這是需要注意主儡,如果不是對(duì)于安全性要求的情況奖唯,不建議每次都申請(qǐng),因?yàn)闀?huì)增加業(yè)務(wù)耗時(shí)糜值;比如只在登陸時(shí)申請(qǐng),然后使用JWT的過期時(shí)間或其他手段來保證JWT的有效性坯墨;

Acesss Token寂汇,Refresh Token

JWT最大的優(yōu)勢(shì)是服務(wù)器不再需要存儲(chǔ)Session,使得服務(wù)器認(rèn)證鑒權(quán)業(yè)務(wù)可以方便擴(kuò)展捣染。這也是JWT最大的缺點(diǎn)由于服務(wù)器不需要存儲(chǔ)Session狀態(tài)骄瓣,因此使用過程中無法廢棄某個(gè)Token,或者更改Token的權(quán)限耍攘。也就是說一旦JWT簽發(fā)了榕栏,到期之前就會(huì)始終有效。我們可以基于上面提到的問題做一些改進(jìn)蕾各。

前面講的Token扒磁,都是Acesss Token,也就是訪問資源接口時(shí)所需要的Token式曲,還有另外一種Token妨托,Refresh Token缸榛。一般情況下,Refresh Token的有效期會(huì)比較長兰伤。而Access Token的有效期比較短内颗,當(dāng)Acesss Token由于過期而失效時(shí),使用Refresh Token就可以獲取到新的Token敦腔,如果Refresh Token也失效了均澳,用戶就只能重新登錄了。Refresh Token及過期時(shí)間是存儲(chǔ)在服務(wù)器的數(shù)據(jù)庫中符衔,只有在申請(qǐng)新的Acesss Token時(shí)才會(huì)驗(yàn)證找前,不會(huì)對(duì)業(yè)務(wù)接口響應(yīng)時(shí)間造成影響,也不需要向Session一樣一直保持在內(nèi)存中以應(yīng)對(duì)大量的請(qǐng)求柏腻。

一個(gè)簡(jiǎn)單的JWT使用示例

準(zhǔn)備

npm i --save koa koa-route koa-bodyparser @koa/cors jwt-simple

服務(wù)端代碼

const Koa = require("koa");
const app = new Koa();
const route = require('koa-route');
var bodyParser = require('koa-bodyparser');
const jwt = require('jwt-simple');
const cors = require('@koa/cors');

const secret = 'your_secret_string'; // 加密用的SECRET字符串纸厉,可隨意更改
app.use(bodyParser()); // 處理post請(qǐng)求的參數(shù)

const login = ctx => {
    const req = ctx.request.body;
    const userName = req.userName;
    const expires = Date.now() + 1000 * 60; // 為了方便測(cè)試,設(shè)置超時(shí)時(shí)間為一分鐘后
    
    const payload = { 
        iss: userName,
        exp: expires
    };
    const Token = jwt.encode(payload, secret);
    ctx.response.body = {
        data: Token,
        msg: '登陸成功'
    };
}
const getUserName = ctx => {
    const token = ctx.get('authorization').split(" ")[1];
    const payload = jwt.decode(token, secret);
    
    // 每次請(qǐng)求只判斷Token是否過期五嫂,不重新去更新Token過期時(shí)間(更新不更新Token的過期時(shí)間主要看實(shí)際的應(yīng)用場(chǎng)景)
    if(Date.now() >  payload.exp) {
        ctx.response.body = {
            errorMsg: 'Token已過期颗品,請(qǐng)重新登錄'
        };
    } else {
        ctx.response.body = {
            data: {
                username: payload.iss,
            },
            msg: '獲取用戶名成功',
            errorMsg: ''
        };
    }
    
}
app.use(cors());
app.use(route.post('/login', login));
app.use(route.get('/getUsername', getUserName));
app.listen(3200, () => {
    console.log('啟動(dòng)成功');
});


客戶端代碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JWT-demo</title>
    <style>
        .login-wrap {
            height: 100px;
            width: 200px;
            border: 1px solid #ccc;
            padding: 20px;
            margin-bottom: 20px;
        }
    </style>
</head>

<body>
    <div class="login-wrap">
        <input type="text" placeholder="用戶名" class="userName">
        <br>
        <input type="password" placeholder="密碼" class="password">
        <br>
        <br>
        <button class="btn">登陸</button>
    </div>
    
    <button class="btn1">獲取用戶名</button>
    <p class="username"></p>
</body>
<script>
    var btn = document.querySelector('.btn');
    
    btn.onclick = function () {
        var userName = document.querySelector('.userName').value;
        var password = document.querySelector('.password').value;
        
        fetch('http://localhost:3200/login', {
            method: 'POST', 
            body: `userName=${userName}&password=${password}`,
            headers:{
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            mode: 'cors' // no-cors, cors, *same-origin
        })
            .then(function (response) {
                return response.json();
            })
            .then(function (res) {
                // 獲取到Token,將Token放在localStorage
                document.cookie = `token=${res.data}`;
                localStorage.setItem('token', res.data);
                localStorage.setItem('token_exp', new Date().getTime());
                alert(res.msg);
            })
            .catch(err => {
                message.error(`本地測(cè)試錯(cuò)誤 ${err.message}`);
                console.error('本地測(cè)試錯(cuò)誤', err);
            });
    }
    var btn1 = document.querySelector('.btn1');
    btn1.onclick = function () {
        var username = document.querySelector('.username');
        const token = localStorage.getItem('token');
        fetch('http://localhost:3200/getUsername', {
            headers:{
                'Authorization': 'Bearer ' + token
            },
            mode: 'cors' // no-cors, cors, *same-origin
        })
            .then(function (response) {
                return response.json();
            })
            .then(function (res) {
                console.log('返回用戶信息結(jié)果', res);
                if(res.errorMsg !== '') {
                    alert(res.errorMsg);
                    username.innerHTML = '';
                } else {
                    username.innerHTML = `姓名:${res.data.username}`;
                }
                
            })
            .catch(err => {
                console.error(err);
            });
    }
</script>

</html>

運(yùn)行代碼

區(qū)別

Cookie和Session的區(qū)別

  • 存儲(chǔ)位置不同:cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上
  • 隱私策略不同:cookie不是很安全沃缘, 別人可以分析存放在本地的cookie并進(jìn)行cookie欺騙躯枢,考慮到安全應(yīng)當(dāng)使用session
  • session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多槐臀,就會(huì)比較占用你服務(wù)器的性能锄蹂,考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用cookie
  • 存儲(chǔ)大小不同:?jiǎn)蝹€(gè)cookie保存的數(shù)據(jù)不能超過4k, 很多瀏覽器都限制一個(gè)站點(diǎn)最多保存20個(gè)cookie

Token和Session的區(qū)別

Session是一種HTTP儲(chǔ)存機(jī)制水慨, 為無狀態(tài)的HTTP提供持久機(jī)制; Token就是令牌得糜, 比如你授權(quán)(登錄)一個(gè)程序時(shí),它就是個(gè)依據(jù)晰洒,判斷你是否已經(jīng)授權(quán)該軟件朝抖;

Session和Token并不矛盾,作為身份認(rèn)證Token安全性比Session好谍珊,因?yàn)槊恳粋€(gè)請(qǐng)求都有簽名還能防止監(jiān)聽以及重放攻擊治宣,而Session就必須依賴鏈路層來保障通訊安全了。如上所說砌滞,如果你需要實(shí)現(xiàn)有狀態(tài)的回話侮邀,仍然可以增加Session來在服務(wù)端保存一些狀態(tài)。

總結(jié)

無論是cookie session 還是token贝润,在不同場(chǎng)景下都會(huì)有各自的應(yīng)用绊茧,在相同的場(chǎng)景下,有些問題用cookie + session 或者token都可以去解決問題题暖,對(duì)于技術(shù)來說按傅,存在即合理捉超,沒有誰好誰不好,我們要做的是讀懂他們唯绍,了解他們的運(yùn)行原理拼岳,在我們遇到問題時(shí),能有法可循况芒。本地存儲(chǔ)的出現(xiàn)惜纸,讓我們能夠基于此創(chuàng)建更豐富的web應(yīng)用,同時(shí)也意味著绝骚,我們的項(xiàng)目逐漸復(fù)雜起來耐版。但萬變不離其宗,我們掌握了事物的本質(zhì)压汪,多復(fù)雜的項(xiàng)目粪牲,我們都能一層一層的撥開他們,用心去學(xué)止剖。其實(shí)腺阳,我們生而為人,也是這個(gè)道理穿香,我說的對(duì)嘛亭引?大家,加油??皮获!

參考鏈接:
詳解 Cookie焙蚓,Session,Token

我是前端dog君洒宝,一名95后前端小兵购公。對(duì)前端的熱愛,讓我們?cè)诖讼嗑垩愀瑁M@篇文章君丁,能幫助到您,也同時(shí)希望能交到志同道合的小伙伴将宪,共同發(fā)展,一起進(jìn)步橡庞。我的微信號(hào)dm120225较坛,備注簡(jiǎn)書,期待您的光臨扒最。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丑勤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吧趣,更是在濱河造成了極大的恐慌法竞,老刑警劉巖耙厚,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異岔霸,居然都是意外死亡薛躬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門呆细,熙熙樓的掌柜王于貴愁眉苦臉地迎上來型宝,“玉大人,你說我怎么就攤上這事絮爷∨亢ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵坑夯,是天一觀的道長岖寞。 經(jīng)常有香客問我,道長柜蜈,這世上最難降的妖魔是什么仗谆? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮跨释,結(jié)果婚禮上胸私,老公的妹妹穿的比我還像新娘。我一直安慰自己鳖谈,他們只是感情好岁疼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缆娃,像睡著了一般捷绒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贯要,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天暖侨,我揣著相機(jī)與錄音,去河邊找鬼崇渗。 笑死字逗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宅广。 我是一名探鬼主播葫掉,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼跟狱!你這毒婦竟也來了俭厚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤驶臊,失蹤者是張志新(化名)和其女友劉穎挪挤,沒想到半個(gè)月后叼丑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扛门,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年鸠信,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尖飞。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡症副,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出政基,到底是詐尸還是另有隱情贞铣,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布沮明,位于F島的核電站辕坝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏荐健。R本人自食惡果不足惜酱畅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望江场。 院中可真熱鬧纺酸,春花似錦、人聲如沸址否。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佑附。三九已至樊诺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間音同,已是汗流浹背词爬。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留权均,地道東北人顿膨。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像叽赊,于是被迫代替她去往敵國和親虽惭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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