OAuth 授權(quán)介紹

如今網(wǎng)絡應用梦裂,手機app越來越多童社,每個app都需要一個賬號告匠,對于個人來說就變得繁瑣戈抄,需要記住都賬號密碼很多。 為了解決這些問題以及安全問題后专,各種登錄方式陸續(xù)誕生.

OAuth 登錄

OAuth是open authentication的縮寫划鸽,OAuth并不是API或服務:它是一種開放的授權(quán)標準,任何人都可以實現(xiàn)戚哎。OAuth是用來為第三方應用提供“secure delegated access”的一個標準裸诽。OAuth通過https和訪問令牌對設備,api和服務器進行認證型凳,而不需要用戶名密碼丈冬。OAuth有1.0和2.0兩個版本,他們之間完全不同啰脚,不能一起使用殷蛇, 兩個版本之間也不兼容。目前OAuth 2.0使用比較廣泛橄浓,這里主要介紹2.0版本粒梦。

為什么要用Oauth

OAuth是相對直接身份驗證模式而創(chuàng)建的。直接身份驗證模式通過HTTP進行驗證荸实,提示用戶輸入用戶名和密碼匀们。基本身份驗證仍然是服務器端應用程序API身份驗證的原始形式:然而用戶發(fā)送的是API key ID和 secret 進行驗證而不是發(fā)送用戶名和密碼准给。在使用OAuth之前泄朴,網(wǎng)站會提示在網(wǎng)頁中輸入用戶名和密碼重抖,并且會以你的身份登錄你的數(shù)據(jù)(例如您的Gmail帳戶)。這通常稱為密碼反模式祖灰。

為了創(chuàng)建更好的web系統(tǒng)钟沛,單點登錄(SSO)經(jīng)常被使用。SSO登錄涉及到聯(lián)合身份的創(chuàng)建局扶。在這種情況下恨统,最終應用程序與身份提供者(authorize endpoint)進行對話,并且身份提供者生成一個加密簽名的令牌(token)三妈,并將其交給應用程序以驗證用戶身份畜埋。如果簽名能夠被驗證,應用程序就會信任身份提供者畴蒲,驗證流程如下:

image.png

OAuth API

我們構(gòu)建API的方式也發(fā)生了很多變化悠鞍。 在2005年,人們研究用WS- *來構(gòu)建Web服務模燥。 現(xiàn)在咖祭,大多數(shù)開發(fā)人員已轉(zhuǎn)向REST和無狀態(tài)API。 簡而言之蔫骂,REST是HTTP命令通過網(wǎng)絡推送JSON數(shù)據(jù)包心肪。

開發(fā)人員構(gòu)建了大量的API。 現(xiàn)在可能會在會議室聽到“ API economy”這個常見詞纠吴。 公司需要保護REST API, 同時允許許多設備訪問它們慧瘤。 過去戴已,只要需要輸入用戶名/密碼,應用程序?qū)⒅苯右阅愕纳矸莸卿洝?這引起了委托授權(quán)問題锅减。
“如何允許應用訪問我的數(shù)據(jù)而不必輸入密碼糖儡?”
以下 是一個應用程序,詢問它是否可以代表你訪問數(shù)據(jù)怔匣。


image.png

這是OAuth握联。

OAuth是REST / API的委托授權(quán)框架。 它使應用程序無需提供用戶密碼即可獲得對用戶數(shù)據(jù)的有限訪問權(quán)限(scopes)每瞒。 它使身份驗證與授權(quán)脫鉤金闽,并支持解決不同設備功能的多個用例。 它支持服務器到服務器應用程序剿骨,基于瀏覽器的應用程序代芜,移動/本地應用程序以及控制臺/電視。
你可以認為這是(對于應用程序)酒店房卡浓利。 如果你有酒店房卡挤庇,則可以進入你的房間钞速。 如何獲得酒店鑰匙卡? 你必須在前臺通過身份驗證才能獲取它嫡秕。 認證并獲得房卡后渴语,您可以訪問整個房間的資源。

簡單來說昆咽,OAuth的就是:

  1. 應用程式要求使用者授權(quán)
  2. 用戶授權(quán)應用并提供證明
  3. 應用程序向服務器提供了獲得令牌(token)的授權(quán)證明
  4. 令牌(token)僅限于訪問用戶為特定應用授權(quán)的內(nèi)容

OAuth 組件

  • Scopes and Consent
  • Actors
  • Clients
  • Tokens
  • Authorization Server
  • Flows

OAuth Scopes

Scopes是我們在應用程序請求權(quán)限時在授權(quán)屏幕上看到的內(nèi)容驾凶。 它們是客戶在請求令牌時要求的權(quán)限束(bundles of permissions)。 這些由應用程序開發(fā)人員在編寫應用程序時進行編碼潮改。


image.png

Scopes使授權(quán)策略決策與執(zhí)行脫鉤狭郑。 這是OAuth的第一個關鍵方面。 權(quán)限位于前面和中間汇在。 它們沒有隱藏在你必須進行反向工程的應用層的后面翰萨。 它們通常列在API文檔中:這是此應用程序要求的范圍。
我們必須獲用戶的同意糕殉。 這稱為首次使用信任亩鬼。 網(wǎng)絡上的用戶體驗發(fā)生了重大變化。 OAuth之前的大多數(shù)人都只是用用戶名和密碼對話框阿蝶。 這是網(wǎng)絡上的一個新概念雳锋,如今已成為流行趨勢。 現(xiàn)在羡洁,你必須授權(quán)并征得同意玷过。
同意(consent)可能會因申請而異。 它可能是時間敏感的范圍(天筑煮,周辛蚊,月),但是并非所有平臺都允許你選擇持續(xù)時間真仲。 當你同意時要注意該應用程序可以代表你執(zhí)行一些操作-例如 LinkedIn向網(wǎng)絡中的每個人發(fā)送垃圾郵件袋马。
OAuth是基于Internet的解決方案,因為它針對每個應用程序秸应。 您通陈橇荩可以登錄到信息中心,以查看你有權(quán)訪問的應用程序并撤消同意软啼。

OAuth Actors

OAuth流程中的actors如下:

  • 資源所有者(Resource Owner):擁有資源服務器中的數(shù)據(jù)桑谍。 例如,我是我的Facebook個人資料的資源所有者祸挪。
  • 資源服務器(Resource Server):用于存儲應用程序要訪問的數(shù)據(jù)的API
  • 客戶端(Client):想要訪問你的數(shù)據(jù)的應用程序
  • 授權(quán)服務器(Authorization Server):OAuth的主要引擎
image.png

資源所有者有不同的角色:它可以是最終用戶霉囚,但也可以是公司。
客戶端可以是公開或者保密的。 在OAuth中盈罐,兩者之間有很大的區(qū)別榜跌。 機密客戶端可以用來來存儲機密。 它們不在臺式機上運行或不在應用商店中分發(fā)盅粪。 人們無法對其進行反向工程并獲得密鑰钓葫。 它們在受保護的區(qū)域內(nèi)運行,終端用戶無法訪問它們票顾。
公共客戶端是瀏覽器础浮,移動應用程序和IoT設備。


image.png

客戶端注冊也是OAuth的關鍵組成部分奠骄, 就像OAuth的DMV豆同。你需要為應用獲取license, 這是您的應用徽標在授權(quán)對話框中顯示的方式含鳞。

OAuth Tokens

訪問令牌(access token)是客戶端用來訪問資源服務器(API)的令牌影锈。 它們生命走起是短暫的,通常是幾分鐘或者幾小時蝉绷,而不是幾天或者一個月鸭廷。 我們通過公共客戶端就可以獲取訪問令牌。 它們旨在優(yōu)化互聯(lián)網(wǎng)規(guī)模問題熔吗。 由于這些令牌的壽命很短且可以擴展辆床,因此無法撤消,只需要等待它們超時即可桅狠。

另一個令牌是刷新令牌(refresh token), 他們壽命很長讼载,通常是幾天,幾個月或者幾年中跌, 可以用他們來獲取新令牌维雇。 為了獲得刷新令牌,應用程序通常需要通過具有身份驗證的機密客戶端晒他。
刷新令牌可以被撤消。 在控制臺中撤消應用程序的訪問權(quán)限時逸贾,就是殺死其刷新令牌陨仅。 這使你能夠強制客戶端旋轉(zhuǎn)秘鑰, 使用刷新令牌來獲取新的訪問令牌铝侵,而訪問令牌正在通過網(wǎng)絡訪問所有API資源灼伤。 每次刷新訪問令牌時,都會得到一個新的加密簽名的令牌玛界。 密鑰旋轉(zhuǎn)內(nèi)置于系統(tǒng)中神得。
OAuth規(guī)范沒有定義令牌是什么盒粮。 它可以是你想要的任何格式余黎。 但是通常這些令牌為JSON Web Token(標準)颖侄。 簡而言之鸟雏,JWT是令牌認證的安全且值得信賴的標準。 JWT允許使用簽名對信息(稱為聲明)進行數(shù)字簽名览祖,并可以在以后使用秘密簽名密鑰進行驗證孝鹊。
令牌是從從授權(quán)服務器上獲取的,兩個主要端點是授權(quán)端點(authorize endpoint)和令牌端點(token endpoint.)展蒂。 根據(jù)不同的使用情況將它們分開又活, 授權(quán)端點是獲得用戶同意和授權(quán)的地方,他們將返回表明用戶已同意的認證授權(quán)(authorization grant)锰悼, 然后將授權(quán)傳遞到令牌端點柳骄,令牌端點處理授權(quán),并說“好箕般,這是你的刷新令牌和訪問令牌”耐薯。


image.png

可以使用訪問令牌來訪問API。 過期后隘世,必須使用刷新令牌返回令牌端點可柿,以獲取新的訪問令牌。
對于開發(fā)人員來說丙者,OAuth的最大痛苦之一就是必須管理刷新令牌复斥。你將狀態(tài)管理推給每個客戶端開發(fā)人員,你可以獲得密鑰輪換的好處械媒,但給開發(fā)人員帶來了很多痛苦目锭。這就是開發(fā)人員喜歡API密鑰的原因。他們可以只復制/粘貼它們纷捞, API密鑰對開發(fā)人員來說非常方便痢虹,但對安全性卻很不利。
還有收費問題主儡,讓開發(fā)人員執(zhí)行OAuth流程可以提高安全性奖唯,但是會遇到更多麻煩。工具箱和平臺有機會簡化工作并幫助令牌管理糜值。幸運的是丰捷,OAuth現(xiàn)在已經(jīng)很成熟了,你最喜歡的語言或框架很可能具有可用來簡化事情的工具寂汇。
我們已經(jīng)討論了客戶端類型病往,令牌類型和授權(quán)服務器的端點,以及如何將其傳遞給資源服務器骄瓣。提到了兩種不同的流程:獲得授權(quán)和獲得令牌停巷。這些不必發(fā)生在同一頻道上。前通道(front channel)是瀏覽器中經(jīng)過的通道,瀏覽器將用戶重定向到授權(quán)服務器畔勤,用戶表示同意蕾各,這是在用戶的瀏覽器上發(fā)生的。一旦用戶獲得了授權(quán)授權(quán)并將其交給應用程序硼被,客戶端應用程序就不再需要使用瀏覽器來完成OAuth流以獲取令牌示损。
令牌應由客戶端應用程序使用,以便它可以代表你訪問資源嚷硫。 我們稱其為后通道(back channel)检访。 后通道是直接從客戶端應用程序到資源服務器的HTTP調(diào)用,以交換令牌的認證授權(quán)仔掸。 這些通道用于不同的流程脆贵,具體取決于你擁有的設備功能。


image.png

例如起暮,您通過用戶代理授權(quán)的前端渠道流可能如下所示:

  1. 資源所有者開始流程以委派對受保護資源的訪問
  2. 客戶端通過瀏覽器重定向到授權(quán)服務器上的授權(quán)端點發(fā)送具有所需作用域的授權(quán)請求
  3. Authorization Server返回一個同意對話框卖氨,說“您是否允許該應用程序訪問這些作用域?” 當然负懦,您需要對應用程序進行身份驗證筒捺,因此,如果您未對資源服務器進行身份驗證纸厉,它將要求您登錄系吭。 如果您已經(jīng)有一個緩存的會話Cookie,則只會看到“同意”對話框颗品。 查看同意對話框肯尺,并同意。
  4. 授權(quán)授予通過瀏覽器重定向傳遞回應用程序躯枢。 這一切都發(fā)生在前通道上则吟。


    image.png

該流中也有一個變化,稱為隱式流锄蹂。
Request:

GET https://accounts.google.com/o/oauth2/auth?scope=gmail.insert gmail.send
&redirect_uri=https://app.example.com/oauth2/callback
&response_type=code&client_id=812741506391
&state=af0ifjsldkj

這是一個帶有大量查詢參數(shù)的GET請求(出于示例目的氓仲,未經(jīng)URL編碼)。 scope來自Gmail的API得糜。 redirect_uri是授權(quán)授權(quán)應返回到的客戶端應用程序的URL敬扛。 這應該與客戶端注冊過程中的值(在DMV上)匹配。 response_type會改變OAuth流掀亩。clieny ID是注冊獲取的。 state是一個安全標志欢顷,類似于XRSF槽棍。

Response

HTTP/1.1 302 Found
Location: https://app.example.com/oauth2/callback?
code=MsCeLvIaQm6bTrgtp7&state=af0ifjsldkj

返回的code是authorization grant,state是為了確保它不是偽造的,并且來自同一請求炼七。完成前通道后缆巧,后通道流就會開始,將交換授權(quán)碼來獲取訪問令牌豌拙。

客戶端應用程序使用機密的客戶端credentials和 client ID將訪問令牌請求發(fā)送到授權(quán)服務器上的令牌端點(token endpoint)陕悬。 此過程發(fā)送授權(quán)代碼以獲取訪問令牌和(可選)刷新令牌。 客戶端使用訪問令牌訪問受保護的資源按傅。


image.png

以下是HTTP
Request

POST /oauth2/v3/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=MsCeLvIaQm6bTrgtp7&client_id=812741506391&client_secret={client_secret}&redirect_uri=https://app.example.com/oauth2/callback&grant_type=authorization_code

grant_type是OAuth的可擴展部分,這是授權(quán)代碼捉超。 它很靈活,使他們可以采用不同的方式來描述這些grant唯绍。 這是OAuth流的最常見類型拼岳。

Reponse

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA"
}

Reponse為JSON。兩種方式使用令牌: 1.在客戶端中設置一個計時器况芒。2.捕獲錯誤并嘗試獲取新令牌惜纸。
獲得訪問令牌后,可以在Authentication Header中使用訪問令牌(使用token_type作為前綴)來發(fā)出受保護的資源請求绝骚。

curl -H "Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA" \
  https://www.googleapis.com/gmail/v1/users/1444587525/messages

前通道耐版,后通道,不同的端點和不同的客戶端压汪。 我們必須針對不同的場景將它們混合使用和匹配粪牲。 這樣會提高Oauth的復雜度

OAuth flow

  1. 第一種flow就是所謂的隱式flow。之所以稱為隱式flow(Implicit Flow.)蛾魄,是因為所有通信都是通過瀏覽器進行的虑瀑。沒有后端服務器為訪問令牌兌換授權(quán)。 SPA是該流程用例的一個很好的例子滴须。此flow也稱為2 Legged OAuth舌狗。
    隱式flow僅僅針對瀏覽器的公共客戶端進行了優(yōu)化。訪問令牌直接從授權(quán)請求中返回(僅前通道)扔水,它通常不支持刷新令牌痛侍。假定資源所有者和公共客戶端在同一設備上。由于一切都發(fā)生在瀏覽器上魔市,因此它最容易受到安全威脅的攻擊主届。

  2. 黃金標準是使用前通道和后通道的授權(quán)碼流(Authorization Code Flow),也稱為3 Legged待德。這就是我們在本文中討論最多的內(nèi)容君丁。客戶端應用程序使用前通道流來獲取授權(quán)碼授予将宪』婷疲客戶端應用程序使用后向通道將授權(quán)代碼授權(quán)交換為訪問令牌(以及可選的刷新令牌)橡庞。假定資源所有者和客戶端應用程序位于單獨的設備上。這是最安全的流程印蔗,因為您可以對客戶端進行身份驗證以兌換授權(quán)扒最,并且令牌永遠不會通過用戶代理傳遞。不僅有隱式和授權(quán)碼流华嘹,您還可以使用OAuth進行其他處理吧趣。同樣,OAuth更像是一個框架耙厚。

  3. 對于服務器到服務器的方案强挫,您可能要使用客戶端憑據(jù)流(Client Credential Flow)。在這種情況下颜曾,客戶端應用程序是一個機密的客戶端纠拔,它以自己身份訪問而不是代表用戶。這更多是服務帳戶類型的情況泛豪。您只需要客戶的憑據(jù)即可完成整個流程稠诲。這是只需要back channel的flow, 通過client 憑據(jù)就能獲取訪問令牌诡曙。它支持共享密鑰或斷言作為使用對稱或非對稱密鑰簽名的客戶端憑據(jù)臀叙。
    對稱密鑰算法是加密算法,只要有密碼价卤,就可以解密任何內(nèi)容劝萤。在保護PDF或.zip文件時通常會發(fā)現(xiàn)這種情況。
    公鑰密碼學或非對稱密碼學是使用密鑰對的密碼系統(tǒng):公鑰和私鑰慎璧。任何人都可以讀取公共密鑰床嫌,并用公鑰加密,所有者可以使用私有密鑰解密胸私。這樣既保證了數(shù)據(jù)安全也無需共享秘鑰厌处。

  4. 還有一種稱為資源所有者密碼流(Resource Owner Password Flow)的舊模式。這與使用用戶名和密碼的直接身份驗證非常相似岁疼,因此不建議使用阔涉。這是本機用戶名/密碼應用程序(例如桌面應用程序)的舊式授權(quán)類型。在此流程中捷绒,您向客戶端應用程序發(fā)送用戶名和密碼瑰排,并從授權(quán)服務器返回訪問令牌。它通常不支持刷新令牌暖侨,并且假定資源所有者和公共客戶端在同一設備上椭住。當API 只支持OAuth,但又有老派客戶需要處理時可以使用字逗。

  5. OAuth的最新流是斷言流(Assertion Flow)京郑,它類似于客戶端憑據(jù)流(Client Credential Flow)显押。添加它是為了打開聯(lián)盟的想法。此流程允許授權(quán)服務器信任來自第三方(例如SAML IdP)的授權(quán)傻挂。授權(quán)服務器信任身份提供者。該斷言用于從令牌端點獲取訪問令牌挖息。這對于投資于SAML或SAML相關技術并允許其與OAuth集成的公司來說非常有用金拒。由于SAML斷言是短暫的,因此此流程中沒有刷新令牌套腹,并且每次斷言到期時都必須繼續(xù)檢索訪問令牌绪抛。

  6. 設備流( Device Flow)不是OAuth規(guī)范中的內(nèi)容。沒有網(wǎng)絡瀏覽器电禀,只有電視之類的控制器幢码。用戶代碼從授權(quán)請求中返回,必須通過使用瀏覽器訪問設備上的URL進行授權(quán)才能兌現(xiàn)尖飞≈⒏保客戶端應用程序使用反向通道流來輪詢訪問令牌和可選的刷新令牌的授權(quán)批準。也受CLI客戶端歡迎政基。

我們使用了不同的參與者和令牌類型贞铣,涵蓋了六種不同的流程。由于客戶的能力沮明,我們需要如何獲得客戶的同意辕坝,進行同意的方式,所以它們是必需的荐健,這給OAuth增加了很多復雜性酱畅。
當人們問您是否支持OAuth時,您必須明確他們的要求江场。他們是在問您是否支持所有六個流程纺酸,還是僅支持主要流程?所有不同的流程之間都有很多可用的粒度扛稽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載吁峻,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末在张,一起剝皮案震驚了整個濱河市用含,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帮匾,老刑警劉巖啄骇,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘟斜,居然都是意外死亡缸夹,警方通過查閱死者的電腦和手機痪寻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虽惭,“玉大人橡类,你說我怎么就攤上這事⊙看剑” “怎么了顾画?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長匆笤。 經(jīng)常有香客問我研侣,道長,這世上最難降的妖魔是什么炮捧? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任庶诡,我火速辦了婚禮,結(jié)果婚禮上咆课,老公的妹妹穿的比我還像新娘末誓。我一直安慰自己,他們只是感情好书蚪,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布基显。 她就那樣靜靜地躺著,像睡著了一般善炫。 火紅的嫁衣襯著肌膚如雪撩幽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天箩艺,我揣著相機與錄音窜醉,去河邊找鬼。 笑死艺谆,一個胖子當著我的面吹牛榨惰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播静汤,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼琅催,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了虫给?” 一聲冷哼從身側(cè)響起藤抡,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抹估,沒想到半個月后缠黍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡药蜻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年瓷式,在試婚紗的時候發(fā)現(xiàn)自己被綠了替饿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡贸典,死狀恐怖视卢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情廊驼,我是刑警寧澤腾夯,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站蔬充,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏班利。R本人自食惡果不足惜饥漫,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罗标。 院中可真熱鬧庸队,春花似錦、人聲如沸闯割。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宙拉。三九已至宾尚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谢澈,已是汗流浹背煌贴。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锥忿,地道東北人牛郑。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像敬鬓,于是被迫代替她去往敵國和親淹朋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350