分布式 - 應(yīng)用會(huì)話管理

Session和Cookie

由于HTTP協(xié)議是無(wú)狀態(tài)的協(xié)議,所以服務(wù)端需要記錄用戶(hù)的狀態(tài)時(shí),就需要用某種機(jī)制來(lái)識(shí)具體的用戶(hù),這個(gè)機(jī)制就是Session歹鱼。 Session是保存在服務(wù)端的,有一個(gè)唯一標(biāo)識(shí)。在大型的網(wǎng)站,一般會(huì)有專(zhuān)門(mén)的Session服務(wù)器集群,這個(gè)時(shí)候 Session 信息都是放在內(nèi)存的蛤高。

思考一下服務(wù)端如何識(shí)別特定的客戶(hù)名党?這個(gè)時(shí)候Cookie就登場(chǎng)了。每次HTTP請(qǐng)求的時(shí)候,客戶(hù)端都會(huì)發(fā)送相應(yīng)的Cookie信息到服務(wù)端。 實(shí)際上大多數(shù)的應(yīng)用都是用 Cookie 來(lái)實(shí)現(xiàn)Session跟蹤的,第一次創(chuàng)建Session的時(shí)候,服務(wù)端會(huì)在HTTP協(xié)議中告訴客戶(hù)端, 需要在 Cookie 里面記錄一個(gè)Session ID,以后每次請(qǐng)求把這個(gè)會(huì)話ID發(fā)送到服務(wù)器,我就知道你是誰(shuí)了。 有人問(wèn),如果客戶(hù)端的瀏覽器禁用了 Cookie 怎么辦氯析?一般這種情況下,會(huì)使用一種叫做URL重寫(xiě)的技術(shù)來(lái)進(jìn)行會(huì)話跟蹤, 即每次HTTP交互,URL后面都會(huì)被附加上一個(gè)諸如 sid=xxxxx 這樣的參數(shù),服務(wù)端據(jù)此來(lái)識(shí)別用戶(hù)。

Cookie其實(shí)還可以用在一些方便用戶(hù)的場(chǎng)景下,設(shè)想你某次登陸過(guò)一個(gè)網(wǎng)站,下次登錄的時(shí)候不想再次輸入賬號(hào)了,怎么辦可霎? 這個(gè)信息可以寫(xiě)到Cookie里面,訪問(wèn)網(wǎng)站的時(shí)候,網(wǎng)站頁(yè)面的腳本可以讀取這個(gè)信息,就自動(dòng)幫你把用戶(hù)名給填了,能夠方便一下用戶(hù)。 這也是Cookie名稱(chēng)的由來(lái),給用戶(hù)的一點(diǎn)甜頭宴杀。

所以,總結(jié)一下:

  1. session 在服務(wù)器端,cookie 在客戶(hù)端(瀏覽器)
  2. session 默認(rèn)被存在在服務(wù)器的一個(gè)文件里(不是內(nèi)存)
  3. session 的運(yùn)行依賴(lài) session id,而 session_id是存在cookie中的,也就是說(shuō),如果瀏覽器禁用了cookie, 同時(shí)session也會(huì)失效(但是可以通過(guò)其它方式實(shí)現(xiàn),比如在 url 中傳遞 session_id)
  4. session 可以放在 文件癣朗、數(shù)據(jù)庫(kù)、或內(nèi)存中都可以旺罢。
  5. 用戶(hù)驗(yàn)證這種場(chǎng)合一般會(huì)用 session 因此,維持一個(gè)會(huì)話的核心就是客戶(hù)端的唯一標(biāo)識(shí),即 session id

種常見(jiàn)的實(shí)現(xiàn)web應(yīng)用會(huì)話管理的方式:

  • 基于server端session的管理方式
  • 基于cookie的管理方式
  • 基于token的管理方式

基于Server端session

在早期web應(yīng)用中,通常使用服務(wù)端session來(lái)管理用戶(hù)的會(huì)話旷余。

1)服務(wù)端session是用戶(hù)第一次訪問(wèn)應(yīng)用時(shí),服務(wù)器就會(huì)創(chuàng)建的對(duì)象,代表用戶(hù)的一次會(huì)話過(guò)程,可以用來(lái)存放數(shù)據(jù)。 服務(wù)器為每一個(gè)session都分配一個(gè)唯一的sessionid,以保證每個(gè)用戶(hù)都有一個(gè)不同的session對(duì)象扁达。

2)服務(wù)器在創(chuàng)建完session后,會(huì)把sessionid通過(guò)cookie返回給用戶(hù)所在的瀏覽器,這樣當(dāng)用戶(hù)第二次及以后向服務(wù)器發(fā)送請(qǐng)求的時(shí)候, 就會(huì)通過(guò)cookie把sessionid傳回給服務(wù)器,以便服務(wù)器能夠根據(jù)sessionid找到與該用戶(hù)對(duì)應(yīng)的session對(duì)象正卧。

3)session通常有失效時(shí)間的設(shè)定,比如2個(gè)小時(shí)。當(dāng)失效時(shí)間到,服務(wù)器會(huì)銷(xiāo)毀之前的session,并創(chuàng)建新的session返回給用戶(hù)跪解。 但是只要用戶(hù)在失效時(shí)間內(nèi),有發(fā)送新的請(qǐng)求給服務(wù)器,通常服務(wù)器都會(huì)把他對(duì)應(yīng)的session的失效時(shí)間根據(jù)當(dāng)前的請(qǐng)求時(shí)間再延長(zhǎng)2個(gè)小時(shí)炉旷。

4)session在一開(kāi)始并不具備會(huì)話管理的作用。它只有在用戶(hù)登錄認(rèn)證成功之后,并且往sesssion對(duì)象里面放入了用戶(hù)登錄成功的憑證, 才能用來(lái)管理會(huì)話。管理會(huì)話的邏輯也很簡(jiǎn)單,只要拿到用戶(hù)的session對(duì)象,看它里面有沒(méi)有登錄成功的憑證,就能判斷這個(gè)用戶(hù)是否已經(jīng)登錄窘行。 當(dāng)用戶(hù)主動(dòng)退出的時(shí)候,會(huì)把它的session對(duì)象里的登錄憑證清掉饥追。 所以在用戶(hù)登錄前或退出后或者session對(duì)象失效時(shí),肯定都是拿不到需要的登錄憑證的。

可簡(jiǎn)單使用流程圖描述如下:

image

主流的web開(kāi)發(fā)平臺(tái)都原生支持這種會(huì)話管理的方式,而且開(kāi)發(fā)起來(lái)很簡(jiǎn)單罐盔。它還有一個(gè)比較大的優(yōu)點(diǎn)就是安全性好, 因?yàn)樵跒g覽器端與服務(wù)器端保持會(huì)話狀態(tài)的媒介始終只是一個(gè)sessionid串,只要這個(gè)串夠隨機(jī),攻擊者就不能輕易冒充他人的sessionid進(jìn)行操作但绕; 除非通過(guò)CSRF或http劫持的方式,才有可能冒充別人進(jìn)行操作;即使冒充成功,也必須被冒充的用戶(hù)session里面包含有效的登錄憑證才行惶看。

但是這種方式也有幾個(gè)問(wèn)題需要解決:

1)這種方式將會(huì)話信息存儲(chǔ)在web服務(wù)器里面,所以在用戶(hù)同時(shí)在線量比較多時(shí),這些會(huì)話信息會(huì)占據(jù)比較多的內(nèi)存捏顺;

2)當(dāng)應(yīng)用采用集群部署的時(shí)候,會(huì)遇到多臺(tái)web服務(wù)器之間如何做session共享的問(wèn)題。因?yàn)閟ession是由單個(gè)服務(wù)器創(chuàng)建的, 但是處理用戶(hù)請(qǐng)求的服務(wù)器不一定是那個(gè)創(chuàng)建session的服務(wù)器,這樣他就拿不到之前已經(jīng)放入到session中的登錄憑證之類(lèi)的信息了纬黎;

3)多個(gè)應(yīng)用要共享session時(shí),除了以上問(wèn)題,還會(huì)遇到跨域問(wèn)題,因?yàn)椴煌膽?yīng)用可能部署的主機(jī)不一樣,需要在各個(gè)應(yīng)用做好cookie跨域的處理幅骄。

針對(duì)問(wèn)題1和問(wèn)題2,我見(jiàn)過(guò)的解決方案是采用redis/memcached這種中間服務(wù)器來(lái)管理session的增刪改查, 一來(lái)減輕web服務(wù)器的負(fù)擔(dān),二來(lái)解決不同web服務(wù)器共享session的問(wèn)題。

針對(duì)問(wèn)題3,由于服務(wù)端的session依賴(lài)cookie來(lái)傳遞sessionid,所以在實(shí)際項(xiàng)目中,只要解決各個(gè)項(xiàng)目里面如何實(shí)現(xiàn)sessionid的cookie跨域訪問(wèn)即可, 這個(gè)是可以實(shí)現(xiàn)的,就是比較麻煩,前后端有可能都要做處理莹桅。

如果在一些小型的web應(yīng)用中使用,可以不用考慮上面三個(gè)問(wèn)題,所以很適合這種方式昌执。

基于cookie

由于前一種方式會(huì)增加服務(wù)器的負(fù)擔(dān)和架構(gòu)的復(fù)雜性,所以后來(lái)就有人想出直接把用戶(hù)的登錄憑證直接存到客戶(hù)端的方案, 當(dāng)用戶(hù)登錄成功之后,把登錄憑證寫(xiě)到cookie里面,并給cookie設(shè)置有效期,后續(xù)請(qǐng)求直接驗(yàn)證存有登錄憑證的cookie是否存在以及憑證是否有效, 即可判斷用戶(hù)的登錄狀態(tài)。使用它來(lái)實(shí)現(xiàn)會(huì)話管理的整體流程如下:

1)用戶(hù)發(fā)起登錄請(qǐng)求,服務(wù)端根據(jù)傳入的用戶(hù)密碼之類(lèi)的身份信息,驗(yàn)證用戶(hù)是否滿(mǎn)足登錄條件,如果滿(mǎn)足,就根據(jù)用戶(hù)信息創(chuàng)建一個(gè)登錄憑證, 這個(gè)登錄憑證簡(jiǎn)單來(lái)說(shuō)就是一個(gè)對(duì)象,最簡(jiǎn)單的形式可以只包含用戶(hù)id,憑證創(chuàng)建時(shí)間和過(guò)期時(shí)間三個(gè)值诈泼。

2)服務(wù)端把上一步創(chuàng)建好的登錄憑證,先對(duì)它做數(shù)字簽名,然后再用對(duì)稱(chēng)加密算法做加密處理,將簽名懂拾、加密后的字串,寫(xiě)入cookie。 cookie的名字必須固定(如ticket),因?yàn)楹竺嬖佾@取的時(shí)候,還得根據(jù)這個(gè)名字來(lái)獲取cookie值铐达。 這一步添加數(shù)字簽名的目的是防止登錄憑證里的信息被篡改,因?yàn)橐坏┬畔⒈淮鄹?那么下一步做簽名驗(yàn)證的時(shí)候肯定會(huì)失敗岖赋。 做加密的目的,是防止cookie被別人截取的時(shí)候,無(wú)法輕易讀到其中的用戶(hù)信息。

3)用戶(hù)登錄后發(fā)起后續(xù)請(qǐng)求,服務(wù)端根據(jù)上一步存登錄憑證的cookie名字,獲取到相關(guān)的cookie值瓮孙。然后先做解密處理,再做數(shù)字簽名的認(rèn)證, 如果這兩步都失敗,說(shuō)明這個(gè)登錄憑證非法唐断;如果這兩步成功,接著就可以拿到原始存入的登錄憑證了。然后用這個(gè)憑證的過(guò)期時(shí)間和當(dāng)前時(shí)間做對(duì)比, 判斷憑證是否過(guò)期,如果過(guò)期,就需要用戶(hù)再重新登錄杭抠;如果未過(guò)期,則允許請(qǐng)求繼續(xù)脸甘。

可簡(jiǎn)單使用流程圖描述如下:

image

它的缺點(diǎn)也比較明顯:

1)cookie有大小限制,存儲(chǔ)不了太多數(shù)據(jù)

2)每次傳送cookie,增加了請(qǐng)求的數(shù)量,對(duì)訪問(wèn)性能也有影響;

3)也有跨域問(wèn)題,畢竟還是要用cookie偏灿。

相比起第一種方式,基于cookie方案明顯還是要好一些,目前好多web開(kāi)發(fā)平臺(tái)或框架都默認(rèn)使用這種方式來(lái)做會(huì)話管理丹诀。

跨域的問(wèn)題可以用CORS(跨域資源共享)的方式來(lái)快速解決。

基于token

前面兩種會(huì)話管理方式因?yàn)槎加玫絚ookie,不適合用在移動(dòng)端native app里面,native app不好管理cookie,畢竟它不是瀏覽器翁垂。 這兩種方案都不適合用來(lái)做純api服務(wù)的登錄認(rèn)證,就要考慮第三種會(huì)話管理方式,也就是token認(rèn)證铆遭。

這種方式從流程和實(shí)現(xiàn)上來(lái)說(shuō),跟cookie-based的方式?jīng)]有太多區(qū)別,只不過(guò)cookie-based里面寫(xiě)到cookie里面的ticket在這種方式下稱(chēng)為token, 這個(gè)token在返回給客戶(hù)端之后,后續(xù)請(qǐng)求都必須通過(guò)url參數(shù)或者是http header的形式,主動(dòng)帶上token, 這樣服務(wù)端接收到請(qǐng)求之后就能直接從http header或者url里面取到token進(jìn)行驗(yàn)證:

這種方式不通過(guò)cookie進(jìn)行token的傳遞,而是每次請(qǐng)求的時(shí)候,主動(dòng)把token加到http header里面或者url后面, 所以即使在native app里面也能使用它來(lái)調(diào)用我們通過(guò)web發(fā)布的api接口。app里面還要做兩件事情:

1)有效存儲(chǔ)token,得保證每次調(diào)接口的時(shí)候都能從同一個(gè)位置拿到同一個(gè)token沿猜;

2)每次調(diào)接口的的代碼里都得把token加到header或者接口地址里面枚荣。

可簡(jiǎn)單使用流程圖描述如下:

image

這種方式同樣適用于網(wǎng)頁(yè)應(yīng)用,token可以存于localStorage或者sessionStorage里面,然后每發(fā)ajax請(qǐng)求的時(shí)候, 都把token拿出來(lái)放到ajax請(qǐng)求的header里即可。不過(guò)如果是非接口的請(qǐng)求,比如直接通過(guò)點(diǎn)擊鏈接請(qǐng)求一個(gè)頁(yè)面這種, 是無(wú)法自動(dòng)帶上token的啼肩。所以這種方式也僅限于走純接口的web應(yīng)用橄妆。

基于token的標(biāo)準(zhǔn)實(shí)現(xiàn): JWT

現(xiàn)在SPA應(yīng)用,前后端完全分離,基于API接口的應(yīng)用越來(lái)越多,這時(shí)候基于token的認(rèn)證就是最好的選擇方式了衙伶。 好在這個(gè)方式的技術(shù)其實(shí)早就有很多實(shí)現(xiàn)了,而且還有現(xiàn)成的標(biāo)準(zhǔn)可用,這個(gè)標(biāo)準(zhǔn)就是JWT(json-web-token)。

JWT本身并沒(méi)有做任何技術(shù)實(shí)現(xiàn),它只是定義了token-based的管理方式該如何實(shí)現(xiàn), 它規(guī)定了token的應(yīng)該包含的標(biāo)準(zhǔn)內(nèi)容以及token的生成過(guò)程和方法呼畸。目前實(shí)現(xiàn)了這個(gè)標(biāo)準(zhǔn)的技術(shù)已經(jīng)有非常多:

官方網(wǎng)站:https://jwt.io/#libraries-io
Git主頁(yè):https://github.com/auth0/java-jwt

SpringSession

生產(chǎn)環(huán)境我們的應(yīng)用示例不可能是單節(jié)點(diǎn)部署, 通常都是多結(jié)點(diǎn)部署, 結(jié)點(diǎn)上層會(huì)進(jìn)行域映射, 實(shí)例之間負(fù)載響應(yīng)請(qǐng)求. 比如常見(jiàn)的Nginx + Tomcat負(fù)載均衡場(chǎng)景中痕支。常用的均衡算法有IP_Hash、輪訓(xùn)蛮原、根據(jù)權(quán)重卧须、隨機(jī)等。不管對(duì)于哪一種負(fù)載均衡算法儒陨,由于Nginx對(duì)不同的請(qǐng)求分發(fā)到某一個(gè)Tomcat花嘶,Tomcat在運(yùn)行的時(shí)候分別是不同的容器里,因此會(huì)出現(xiàn)session不同步或者丟失的問(wèn)題蹦漠。

解決方案

IP_HASH

nginx可以根據(jù)客戶(hù)端IP進(jìn)行負(fù)載均衡椭员,在upstream里設(shè)置ip_hash,就可以針對(duì)同一個(gè)C類(lèi)地址段中的客戶(hù)端選擇同一個(gè)后端服務(wù)器笛园,除非那個(gè)后端服務(wù)器宕了才會(huì)換一個(gè). 這樣如果該類(lèi)QPS高會(huì)導(dǎo)致該臺(tái)服務(wù)器的負(fù)載升高,負(fù)載不均.

nginx基于ip_hash的session管理方案

通過(guò)容器插件

在容器層面擴(kuò)展可共享存儲(chǔ)的插件; 比如基于Tomcat的tomcat-redis-session-manager隘击,基于Jetty的jetty-session-redis等等。好處是對(duì)項(xiàng)目來(lái)說(shuō)是透明的研铆,無(wú)需改動(dòng)代碼埋同。該方案由于過(guò)于依賴(lài)容器,一旦容器升級(jí)或者更換意味著又得從新來(lái)過(guò)棵红。并且代碼不在項(xiàng)目中凶赁,對(duì)開(kāi)發(fā)者來(lái)說(shuō)維護(hù)也是個(gè)問(wèn)題。

會(huì)話管理工具

自己寫(xiě)一套會(huì)話管理的工具類(lèi)逆甜,包括Session管理和Cookie管理虱肄,在需要使用會(huì)話的時(shí)候都從自己的工具類(lèi)中獲取,而工具類(lèi)后端存儲(chǔ)可以放到Redis中交煞。很顯然這個(gè)方案靈活性最大咏窿,但開(kāi)發(fā)需要一些額外的時(shí)間。并且系統(tǒng)中存在兩套Session方案素征,很容易弄錯(cuò)而導(dǎo)致取不到數(shù)據(jù)集嵌。

開(kāi)源解決方案

這里以開(kāi)源框架Spring-Session為例,Spring-Session擴(kuò)展了Servlet的會(huì)話管理(所有的request都會(huì)經(jīng)過(guò)SessionRepositoryFilter稚茅,而 SessionRepositoryFilter是一個(gè)優(yōu)先級(jí)最高的javax.servlet.Filter纸淮,它使用了一個(gè)SessionRepositoryRequestWrapper類(lèi)接管了Http Session的創(chuàng)建和管理工作)平斩,既不依賴(lài)容器亚享,又不需要改動(dòng)代碼. 可插拔, 輕量級(jí). 支持多維度存儲(chǔ);諸如 Redis 、Pivotal GemFire绘面、Jdbc欺税、Mongo 侈沪、Hazelcast等

SpringSession應(yīng)用

SpringMvc項(xiàng)目使用SpringSession

maven依賴(lài)

<dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session</artifactId>
     <version>1.3.1.RELEASE</version>
</dependency>
<dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
     <version>1.3.1.RELEASE</version>
</dependency>

配置web.xml

<filter>
   <filter-name>springSessionRepositoryFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
   <filter-name>springSessionRepositoryFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

配置redis、以及redisHttpSession存儲(chǔ)

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <!-- 將session放入redis -->
    <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="1800" />
    </bean>

    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100" />
        <property name="maxIdle" value="10" />
    </bean>

    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
        <property name="hostName" value="127.0.0.1"/>
        <property name="port" value="6379"/>
        <property name="password" value="" />
        <property name="timeout" value="3000"/>
        <property name="usePool" value="true"/>
        <property name="poolConfig" ref="jedisPoolConfig"/>
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>

</beans>

測(cè)試代碼

@RestController
@RequestMapping("/api/cloud")
public class ApiSessionController extends BaseMultiController {

    private static final Logger LOG = LoggerFactory.getLogger(ApiSessionController.class);

    @Autowired
    protected HttpSession httpSession;

    @GetMapping("/session/put")
    public APIResult sessionPut(){
        httpSession.setAttribute("cloud", JSON.toJSONString(new User("Elonsu", "123456")));
        String userString = (String)httpSession.getAttribute("cloud");
        LOG.info("[session][set]:" + userString);
        return APIResult.success(true);
    }

    @GetMapping("/session/get")
    public APIResult sessionGet(){
        String userString = (String)httpSession.getAttribute("cloud");
        LOG.info("[session][get]:" + userString);
        User user = JSONObject.parseObject(userString, User.class);
        return APIResult.success(user);
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class User implements Serializable {
        private String username;
        private String password;
    }

}

測(cè)試輸出

啟兩個(gè)容器實(shí)例,端口分別使用8080和8081進(jìn)行訪問(wèn)

實(shí)例1訪問(wèn)結(jié)果

image

實(shí)例2訪問(wèn)結(jié)果

image

查看redis中存儲(chǔ)的session

image

應(yīng)用SpringSession

maven依賴(lài)

<dependencies>
   <dependency>
           <groupId>org.springframework.session</groupId>
           <artifactId>spring-session</artifactId>
           <version>1.3.1.RELEASE</version>
   </dependency>
   <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-redis</artifactId>
   </dependency>
</dependencies>

啟動(dòng)主類(lèi)增加注解

啟動(dòng)類(lèi)上增加注解@EnableRedisHttpSession

@Configuration
@SpringBootApplication
@EnableAutoConfiguration
@EnableRedisHttpSession
public class Application extends WebMvcStrap {

    protected final static Logger LOG = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

應(yīng)用配置文件配置

應(yīng)用配置文件application.properties 增加如下配置

# spring redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
# spring session
spring.session.store-type=redis
server.session.timeout=5

官方文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晚凿,一起剝皮案震驚了整個(gè)濱河市亭罪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歼秽,老刑警劉巖应役,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異燥筷,居然都是意外死亡箩祥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)肆氓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)袍祖,“玉大人,你說(shuō)我怎么就攤上這事谢揪〗堵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵拨扶,是天一觀的道長(zhǎng)凳鬓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)屈雄,這世上最難降的妖魔是什么村视? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮酒奶,結(jié)果婚禮上蚁孔,老公的妹妹穿的比我還像新娘。我一直安慰自己惋嚎,他們只是感情好杠氢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著另伍,像睡著了一般鼻百。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上摆尝,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天温艇,我揣著相機(jī)與錄音,去河邊找鬼堕汞。 笑死勺爱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讯检。 我是一名探鬼主播琐鲁,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼卫旱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了围段?” 一聲冷哼從身側(cè)響起顾翼,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奈泪,沒(méi)想到半個(gè)月后适贸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涝桅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年取逾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苹支。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砾隅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出债蜜,到底是詐尸還是另有隱情晴埂,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布寻定,位于F島的核電站儒洛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏狼速。R本人自食惡果不足惜琅锻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望向胡。 院中可真熱鬧恼蓬,春花似錦、人聲如沸僵芹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拇派。三九已至荷辕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間件豌,已是汗流浹背疮方。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茧彤,地道東北人骡显。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蟆盐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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

  • 轉(zhuǎn)載:https://www.cnblogs.com/lyzg/p/6067766.html http是無(wú)狀態(tài)的遭殉,...
    shaolin79閱讀 261評(píng)論 0 1
  • 1. 基于server端session的管理 2. cookie-based的管理方式 3. token-base...
    匆匆歲月閱讀 339評(píng)論 0 0
  • http是無(wú)狀態(tài)的石挂,一次請(qǐng)求結(jié)束,連接斷開(kāi)险污,下次服務(wù)器再收到請(qǐng)求痹愚,它就不知道這個(gè)請(qǐng)求是哪個(gè)用戶(hù)發(fā)過(guò)來(lái)的。當(dāng)然它知道...
    Www劉閱讀 475評(píng)論 4 15
  • http是無(wú)狀態(tài)的蛔糯,一次請(qǐng)求結(jié)束拯腮,連接斷開(kāi),下次服務(wù)器再收到請(qǐng)求蚁飒,它就不知道這個(gè)請(qǐng)求是哪個(gè)用戶(hù)發(fā)過(guò)來(lái)的动壤。當(dāng)然它知道...
    Blues2013閱讀 280評(píng)論 0 0
  • 頭腦一熱,就點(diǎn)了個(gè)挑戰(zhàn)日更淮逻。差不多沒(méi)有猶豫琼懊,現(xiàn)在想來(lái),如果有一絲猶豫可能就不會(huì)在這里說(shuō)了爬早。 不過(guò)至于寫(xiě)什么...
    思想風(fēng)閱讀 187評(píng)論 0 3