別再使用JWT做會(huì)話管理了(一)

不幸的是篡悟,最近我看到越來越多的人建議使用JWT(JSON Web Tokens)來管理其Web應(yīng)用程序中的用戶會(huì)話。這是一個(gè)糟糕的想法匾寝,在這篇文章中搬葬,我將解釋原因。

為了防止任何混淆艳悔,我將首先定義一些術(shù)語:

  • 無狀態(tài)JWT:包含會(huì)話數(shù)據(jù)的JWT令牌急凰,直接編碼到令牌中。

  • 有狀態(tài)JWT:僅包含會(huì)話的引用或ID的JWT令牌猜年。會(huì)話數(shù)據(jù)存儲(chǔ)在服務(wù)器端抡锈。

  • 會(huì)話令牌/ cookie:標(biāo)準(zhǔn)(可選簽名)會(huì)話ID,就像Web框架已經(jīng)使用了很長時(shí)間的形式乔外。會(huì)話數(shù)據(jù)存儲(chǔ)在服務(wù)器端床三。

要明確:本文并不認(rèn)為你永遠(yuǎn)不應(yīng)該使用JWT - 只是它不適合作為會(huì)話機(jī)制,并且這樣使用它是危險(xiǎn)的袁稽。在其他領(lǐng)域勿璃,確實(shí)存在有效的使用場景。在本文的最后推汽,我將簡要介紹其他用例补疑。

前提注意

很多人錯(cuò)誤地將“cookies與JWT”進(jìn)行比較。這種比較完全沒有意義歹撒,它就像將蘋果與橙子進(jìn)行比較莲组。 cookie是一種存儲(chǔ)機(jī)制,而JWT令牌是加密簽名的令牌暖夭。

它們不是對立的 - 相反锹杈,它們可以一起使用或獨(dú)立使用撵孤。正確的比較是“ session與JWT”和“cookie與local storage”。

在這篇文章中竭望,我將把會(huì)話與JWT令牌進(jìn)行比較邪码,偶爾也會(huì)闡述“cookies vs. Local Storage”,這樣做才有意義咬清。

聲稱JWT的優(yōu)勢

當(dāng)人們推薦JWT時(shí)闭专,他們通常會(huì)聲稱以下一項(xiàng)或多項(xiàng)好處:

  • 更容易(水平)縮放

  • 更容易使用

  • 更靈活

  • 更安全

  • 內(nèi)置過期功能

  • 無需向用戶詢問“cookie同意”

  • 防止CSRF

  • 在移動(dòng)設(shè)備上更好用

  • 適用于阻止cookie的用戶

我會(huì)分別闡述這些主張中的每一個(gè),以及為什么它們是錯(cuò)誤的或誤導(dǎo)性的旧烧。下面的一些解釋可能有點(diǎn)含糊不清; 這主要是因?yàn)?strong>聲稱的優(yōu)勢本身也是含糊不清的影钉。我很樂意更新它以給出更具體的說法; 您可以在本文底部找到我的聯(lián)系方式。

更容易(水平)縮放

這是列表中唯一在技術(shù)層面上有些正確的聲明掘剪,但僅限于使用無狀態(tài) JWT令牌平委。然而,現(xiàn)實(shí)是夺谁,幾乎沒有人真正需要這種可擴(kuò)展性廉赔。有許多更簡單的擴(kuò)展方法,除非你的操作規(guī)模像Reddit那么大予权,否則你不需要'無狀態(tài)會(huì)話'昂勉。

擴(kuò)展有狀態(tài)會(huì)話的一些示例:

  1. 在一個(gè)服務(wù)器上運(yùn)行多個(gè)后端進(jìn)程:(在該服務(wù)器上)用一個(gè)Redis守護(hù)進(jìn)程進(jìn)行Session存儲(chǔ)。

  2. 在多個(gè)服務(wù)器上運(yùn)行:使用一個(gè)專用服務(wù)器運(yùn)行Redis進(jìn)行Session存儲(chǔ)扫腺。

  3. 在多個(gè)服務(wù)器上運(yùn)行,在多個(gè)集群中運(yùn)行:粘性(Sticky )Session村象。

這些都是現(xiàn)有軟件良好支持的場景笆环。您的應(yīng)用程序是很有可能永遠(yuǎn)不會(huì)超越第二種情況。

也許你會(huì)想厚者,你應(yīng)該開發(fā)“面向未來”的應(yīng)用程序躁劣,如果你也曾經(jīng)擴(kuò)展超出。然而库菲,在實(shí)踐中账忘,后續(xù)更換會(huì)話機(jī)制是相當(dāng)簡單的。當(dāng)您進(jìn)行轉(zhuǎn)換時(shí)熙宇,唯一的成本是每個(gè)用戶注銷一次鳖擒。預(yù)先實(shí)施使用JWT是不值得的,特別是考慮到我后來會(huì)遇到的缺點(diǎn)烫止。

更容易使用

這點(diǎn)真的不是蒋荚。您必須自己在客戶端和服務(wù)器端處理會(huì)話管理,而標(biāo)準(zhǔn)會(huì)話cookie 只能在開箱即用的情況下工作馆蠕。JWT在任何方面都不容易期升。

更靈活

我還沒有看到有人解釋JWT 如何更靈活惊奇。幾乎每一個(gè)主要的Session的實(shí)現(xiàn)都使您可以存儲(chǔ)任意會(huì)話數(shù)據(jù),這和JWT的工作方式是沒有區(qū)別的播赁。據(jù)我所知颂郎,JWT只是一個(gè)流行語。如果您不同意容为,請隨時(shí)與我聯(lián)系并附帶示例祖秒。

更安全

很多人認(rèn)為JWT令牌“更安全”,因?yàn)樗麄兪褂眉用芗夹g(shù)舟奠。雖然帶簽名的cookie比未簽名的cookie更安全竭缝,但這并不是JWT所獨(dú)有的。好的Session實(shí)現(xiàn)同樣也在使用簽名cookie沼瘫。

使用加密也并不會(huì)神奇地使某些東西更加安全抬纸。它必須服務(wù)于特定目的,并且是針對該特定目的的有效解決方案耿戚。事實(shí)上湿故,錯(cuò)誤使用的加密技術(shù)可能會(huì)降低安全性。

我聽到的“更安全”論點(diǎn)的另一個(gè)解釋是“它們不是作為cookie發(fā)送的”膜蛔。這絕對沒有意義 - 一個(gè)cookie只是一個(gè)HTTP頭坛猪,并且沒有什么不安全的使用cookie。實(shí)際上皂股,cookie 對于像惡意的客戶端代碼此類墅茉,是極其受到良好保護(hù)的。我將在稍后介紹呜呐。

如果您擔(dān)心有人攔截您的會(huì)話cookie就斤,您應(yīng)該只使用TLS - 如果您不使用TLS,任何類型的會(huì)話實(shí)現(xiàn)都是可以截取的蘑辑,包括JWT洋机。

內(nèi)置過期功能

這是無稽之談,而不是一個(gè)有用的功能洋魂。到期也可以在服務(wù)器端實(shí)現(xiàn)绷旗,許多實(shí)現(xiàn)都可以。事實(shí)上副砍,服務(wù)器端到期是可取的 - 它允許您的應(yīng)用程序清理它不再需要的會(huì)話數(shù)據(jù)衔肢,如果您使用有狀態(tài)JWT令牌并依賴其過期機(jī)制,則無法執(zhí)行此操作址晕。

無需向用戶詢問“cookie同意”

完全錯(cuò)了膀懈。沒有“cookie法律”這樣的東西 - 關(guān)于cookie的各種法律實(shí)際上涵蓋了任何類型的持久標(biāo)識(shí)符,這些標(biāo)識(shí)符對于服務(wù)的運(yùn)行并非嚴(yán)格必需谨垃。您可以想到的任何會(huì)話機(jī)制都將由此涵蓋启搂。

簡而言之:

  • 如果您使用的是Session或者Token用于功能性目的(例如硼控,保持用戶登錄),那么無論你使用什么形式存儲(chǔ)管理會(huì)話胳赌,你都不需要詢問用戶同意牢撼。

  • 如果您使用的是會(huì)話令牌或用于其他目的(如分析或跟蹤),不管你如何存儲(chǔ)會(huì)話疑苫,那么你都需要詢問用戶同意熏版。

防止CSRF

事實(shí)并非如此。存儲(chǔ)JWT的方法大致有兩種:

  • 在cookie中:您仍然容易受到CSRF攻擊捍掺,并且仍然需要對其進(jìn)行保護(hù)撼短。

  • 在其他地方,如本地存儲(chǔ)(Local Storage):您不容易受到CSRF攻擊挺勿,但您的應(yīng)用程序或站點(diǎn)需要使用JavaScript去運(yùn)行曲横,這使得自己容易受到完全不同的,可能更糟糕的漏洞類型的攻擊不瓶。下文有更多關(guān)于此的內(nèi)容禾嫉。

唯一正確的CSRF緩解方式是CSRF令牌。會(huì)話機(jī)制與此無關(guān)蚊丐。

在移動(dòng)設(shè)備上更好用

目前在使用的每個(gè)移動(dòng)瀏覽器都支持cookie熙参,因此也支持Session。每個(gè)主要的移動(dòng)開發(fā)框架和任何重要的HTTP庫都是如此麦备。這根本不是一個(gè)問題孽椰。

適用于阻止cookie的用戶

不太可能。用戶不僅可以阻止cookie泥兰,還可以阻止所有持久性方法弄屡。這包括本地存儲(chǔ),以及允許您持久保存會(huì)話的任何其他存儲(chǔ)機(jī)制(使用或不使用JWT)鞋诗。使不使用JWT這里并不重要,這是一個(gè)完全獨(dú)立的問題迈嘹。 讓身份驗(yàn)證在沒有cookie的情況下工作是一個(gè)失敗的原因削彬。

最重要的是,阻止所有 cookie的用戶通承阒伲可以理解為這將破壞他們的身份驗(yàn)證功能融痛,并為他們關(guān)心的網(wǎng)站單獨(dú)解鎖cookie。作為Web開發(fā)人員神僵,這個(gè)問題不是您需要去解決的; 一個(gè)更好的解決方案是向您的用戶解釋您的網(wǎng)站為何需要使用Cookie雁刷。

缺點(diǎn)

現(xiàn)在,上文已經(jīng)涵蓋所有聲稱的特性保礼,以及為什么他們是錯(cuò)誤的沛励,你可能會(huì)想:“哦责语,這不是什么大不了的,沒有關(guān)系目派,即使它對我并沒有沒什么幫助坤候,我仍然用JWT。你錯(cuò)了企蹭。使用JWT作為會(huì)話機(jī)制有很多缺點(diǎn)白筹,其中一些是嚴(yán)重的安全問題。

他們占用更多空間

JWT Tokens并不是很小谅摄。特別是在使用無狀態(tài)JWT令牌時(shí)徒河,所有數(shù)據(jù)都直接編碼到令牌中,您將很快超過cookie或URL的大小限制送漠。您可能打算將它們存儲(chǔ)在本地存儲(chǔ)中 - 但是......

它們不太安全

將JWT存儲(chǔ)在cookie中時(shí)顽照,它與任何其他Session標(biāo)識(shí)符沒有區(qū)別。但是當(dāng)你將JWT存儲(chǔ)在其他地方時(shí)螺男,你很容易受到本文所述的一類新攻擊(特別是“存儲(chǔ)會(huì)話”部分)的攻擊:

回到本地存儲(chǔ)棒厘,這是一個(gè)非常棒的HTML5添加,它為瀏覽器和cookie添加了一個(gè)鍵/值存儲(chǔ)下隧。那么我們應(yīng)該將JWT存儲(chǔ)在本地存儲(chǔ)中嗎奢人?考慮到這些Tokens可以達(dá)到的大小,這可能是有意義的淆院。Cookie通常高出大約4k的存儲(chǔ)空間何乎。對于大型令牌,cookie可能是不可能的土辩,本地存儲(chǔ)將是明顯的解決方案支救。但是,本地存儲(chǔ)不提供cookie所執(zhí)行的任何相同安全機(jī)制拷淘。

與cookie不同各墨,本地存儲(chǔ)不會(huì)隨每個(gè)請求發(fā)送數(shù)據(jù)存儲(chǔ)的內(nèi)容。從本地存儲(chǔ)中檢索數(shù)據(jù)的唯一方法是使用JavaScript启涯,這意味著任何提供通過內(nèi)容安全策略的JavaScript的攻擊者都可以訪問和泄露它贬堵。不僅如此,JavaScript還不關(guān)心或跟蹤數(shù)據(jù)是否通過HTTPS發(fā)送结洼。對于JavaScript而言黎做,存儲(chǔ)的Tokens只是數(shù)據(jù),瀏覽器將像其他任何數(shù)據(jù)一樣對其進(jìn)行操作松忍。

簡而言之蒸殿,使用cookie并不是可選的,無論您是否使用JWT 。

您不能使單個(gè)JWT令牌無效

還有更多的安全問題宏所。與會(huì)話不同 - 無論何時(shí)感覺都可以由服務(wù)器無效 - 個(gè)別無狀態(tài)JWT令牌不能被無效酥艳。根據(jù)設(shè)計(jì),無論發(fā)生什么情況楣铁,它們都將有效玖雁,直到它們到期為止。這意味著盖腕,在檢測到危害后祖今,您無法使攻擊者的會(huì)話無效坪郭。當(dāng)用戶更改密碼時(shí),您也無法使舊會(huì)話無效。

你本質(zhì)上是無能為力的扛吞,如果沒有構(gòu)建復(fù)雜的(有狀態(tài)的<牌痢)基礎(chǔ)設(shè)施來明確地檢測和拒絕它們织咧,就無法“殺死”會(huì)話剃执,從而打敗了使用無狀態(tài)JWT令牌。

數(shù)據(jù)變得陳舊

與此問題有些相關(guān)雅任,還有另一個(gè)潛在的安全問題风范。就像在緩存中一樣,無狀態(tài)令牌中的數(shù)據(jù)最終會(huì)“過期”沪么,并且不再反映數(shù)據(jù)庫中最新版本的數(shù)據(jù)硼婿。

這可能意味著,一個(gè)令牌包含像一個(gè)老的網(wǎng)站URL一些過時(shí)的信息禽车,有人在他們的個(gè)人資料改變寇漫。更嚴(yán)重的是,它也意味著某人有一個(gè)角色的令牌admin殉摔,即使你只是吊銷了其admin作用州胳。因?yàn)槟悴荒芰钆茻o效,你沒有辦法為你免除他們的管理員權(quán)限逸月,除非短暫關(guān)閉整個(gè)系統(tǒng)栓撞。

實(shí)現(xiàn)缺乏實(shí)戰(zhàn)或者根本不存在

您可能會(huì)認(rèn)為所有這些問題都與無狀態(tài)JWT令牌有關(guān),并且您大多數(shù)都是正確的碗硬。但是腐缤,使用有狀態(tài)令牌基本上相當(dāng)于常規(guī)會(huì)話cookie ...但沒有經(jīng)過實(shí)戰(zhàn)考驗(yàn)的實(shí)現(xiàn)。

現(xiàn)有的Session實(shí)現(xiàn)(例如express-sessionExpress)已經(jīng)在生產(chǎn)中運(yùn)行了許多年肛响,并且由于這個(gè)原因,它們的安全性得到了很大的改進(jìn)惜索。使用JWT令牌作為臨時(shí)會(huì)話cookie時(shí)特笋,您不會(huì)獲得這些好處。您將不得不推出自己的實(shí)現(xiàn)(并且很可能在此過程中引入漏洞),或者使用不常見的第三方實(shí)現(xiàn)猎物。

結(jié)論

無狀態(tài)JWT令牌不能無效或更新虎囚,并且會(huì)根據(jù)您存儲(chǔ)它們的位置引入大小問題或安全問題。有狀態(tài)的JWT令牌在功能上與會(huì)話cookie相同蔫磨,但沒有經(jīng)過實(shí)戰(zhàn)考驗(yàn)和經(jīng)過良好審核的實(shí)現(xiàn)或客戶端支持淘讥。

除非您使用Reddit規(guī)模的應(yīng)用程序,否則沒有理由將JWT令牌用作會(huì)話機(jī)制堤如,只需使用Session即可蒲列。

那么...... JWT的優(yōu)點(diǎn)是什么呢?

在本文開頭搀罢,我說JWT 有很好的使用場景蝗岖,但它們不適合作為會(huì)話機(jī)制。JWT特別有效的用例通常是被用作用戶一次性授權(quán)令牌榔至。

來自JSON Web Token規(guī)范

JSON Web令牌(JWT)是一種緊湊的抵赢,URL安全的方式,用于表示在雙方之間轉(zhuǎn)移的聲明唧取。[...]使聲明能夠通過消息驗(yàn)證碼(Message Authentication Code)進(jìn)行數(shù)字簽名或完整性保護(hù)和/或加密铅鲤。

在這種情況下,“聲明”可以是類似“命令”枫弟,一次性授權(quán)或基本上任何其他可以表達(dá)的場景:

你好服務(wù)器B邢享,服務(wù)器A告訴我,我可以<聲稱在這里>媒区,這里是(加密)證明驼仪。

例如,您可能運(yùn)行文件托管服務(wù)袜漩,用戶必須在其中進(jìn)行身份驗(yàn)證才能下載文件绪爸,但文件本身由單獨(dú)的無狀態(tài)“下載服務(wù)器”提供服務(wù)。在這種情況下宙攻,您可能希望讓您的應(yīng)用程序服務(wù)器(服務(wù)器A)發(fā)出一次性“下載令牌(Token)”奠货,然后客戶端可以使用該令牌Token文件從下載服務(wù)器(服務(wù)器B)下載該文件。

以這種方式使用JWT時(shí)座掘,有一些特定的屬性:

  • 令牌是短暫的递惋。它們只需要有效幾分鐘,以允許客戶端啟動(dòng)下載溢陪。

  • 該令牌只能使用一次萍虽。應(yīng)用程序服務(wù)器會(huì)為每次下載發(fā)出一個(gè)新令牌,因此任何一個(gè)令牌只用于請求一次文件形真,然后被丟棄杉编。有沒有持久化狀態(tài)。

  • 應(yīng)用程序服務(wù)器仍使用會(huì)話。只是下載服務(wù)器使用令牌來授權(quán)單個(gè)下載邓馒,因?yàn)樗恍枰志脿顟B(tài)嘶朱。

正如你在這里看到的,結(jié)合Session和JWT Token是完全合理的光酣。它們各有各的目的疏遏,有時(shí)你需要兩者。不要給需要持久化救军、長期保存的數(shù)據(jù)使用JWT财异。

聲明:本文翻譯自《Stop using JWT for sessions》,已征得原文作者同意缤言。如有翻譯不正確或不合理部分宝当,歡迎指出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胆萧,一起剝皮案震驚了整個(gè)濱河市庆揩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跌穗,老刑警劉巖订晌,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蚌吸,居然都是意外死亡锈拨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門羹唠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奕枢,“玉大人,你說我怎么就攤上這事佩微》毂颍” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵哺眯,是天一觀的道長谷浅。 經(jīng)常有香客問我,道長奶卓,這世上最難降的妖魔是什么一疯? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮夺姑,結(jié)果婚禮上墩邀,老公的妹妹穿的比我還像新娘。我一直安慰自己盏浙,他們只是感情好磕蒲,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布留潦。 她就那樣靜靜地躺著,像睡著了一般辣往。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上殖卑,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天站削,我揣著相機(jī)與錄音,去河邊找鬼孵稽。 笑死许起,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的菩鲜。 我是一名探鬼主播园细,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼接校!你這毒婦竟也來了猛频?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蛛勉,失蹤者是張志新(化名)和其女友劉穎鹿寻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诽凌,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毡熏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侣诵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痢法。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杜顺,靈堂內(nèi)的尸體忽然破棺而出财搁,到底是詐尸還是另有隱情,我是刑警寧澤哑舒,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布妇拯,位于F島的核電站,受9級特大地震影響洗鸵,放射性物質(zhì)發(fā)生泄漏越锈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一膘滨、第九天 我趴在偏房一處隱蔽的房頂上張望甘凭。 院中可真熱鬧,春花似錦火邓、人聲如沸丹弱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躲胳。三九已至蜓洪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坯苹,已是汗流浹背隆檀。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粹湃,地道東北人恐仑。 一個(gè)月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像为鳄,于是被迫代替她去往敵國和親裳仆。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

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

  • 摘要: 在Web應(yīng)用中构捡,使用JWT替代session并不是個(gè)好主意 適合JWT的使用場景 抱歉,當(dāng)了回標(biāo)題黨壳猜。我并...
    ThoughtWorks閱讀 276,829評論 157 388
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理勾徽,服務(wù)發(fā)現(xiàn),斷路器统扳,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 構(gòu)建用戶管理微服務(wù)翻譯自:https://springuni.com 構(gòu)建用戶管理微服務(wù)(一):定義領(lǐng)域模型和 R...
    極樂君閱讀 1,519評論 0 10
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架喘帚,建立于...
    Hsinwong閱讀 22,350評論 1 92
  • 1 李建擺攤,跟別人不一樣咒钟,他只挑十幾款自己喜歡的衣服吹由,放在地上賣。一張地?cái)偛贾熳欤瑤资路泠辏枪軄砹耸展司团埽?..
    韓宇良閱讀 479評論 0 3