rfc7519-JSON Web Token

概述

JSON Web令牌(JWT)是一个紧凑的采用URL安全表示方法的声明,用于在两方之间传输。JWT的声明被编码为一个JSON对象,作为一个JSON Web Signature(JWS)结构的有效载荷或作为一个JSON Web Encryption(JWE)结构的明码文本,允许声明被数字签名和进行完整性检查,通过消息认证码(MAC)或者加解密。

备忘录状态

这是一个因特网标准跟踪文档。

本文档是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。已获得公众意见审查,并获准由互联网工程指导小组(IESG)出版。有关因特网标准的更多信息,请参考RFC 5741第二节

版权声明

Copyright (c) 2015 IETF Trust和认证的文档作者。版权所有。

1 介绍

JSON Web令牌(JWT)是一种紧凑的声明表示格式,适用于空间受限的环境,如HTTP授权标头和URI查询参数。JWT的声明被编码为一个JSON对象,作为一个JSON Web Signature(JWS)结构的有效载荷或作为一个JSON Web Encryption(JWE)结构的明码文本,允许声明被数字签名和进行完整性检查,通过消息认证码(MAC)或者加解密。JWT总是使用JWS Compact Serialization或JWE Compact Serialization来表示。

JWT的建议发音与英文单词“jot”相同。

1.1 公共标识

关键字"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 和"OPTIONAL"将被解释为“用于指示要求级别的关键词”RFC2119描述的那样。只有当术语出现在所有大写字母中时才应用该解释。

2 术语

"JSON Web Signature (JWS)", "Base64url Encoding", "Header Parameter", "JOSE Header", "JWS Compact Serialization", "JWS Payload", "JWS Signature", 和"Unsecured JWS"在JWS规范JWS里定义。

"JSON Web Encryption (JWE)", "Content Encryption Key (CEK)", "JWE Compact Serialization", "JWE Encrypted Key", 和"JWE Initialization Vector"在JWE规范JWE里定义。

"Ciphertext", "Digital Signature", "Message Authentication Code (MAC)", and "Plaintext"在"Internet Security Glossary, Version 2"RFC4949里定义。

这些术语由本说明书定义:
JSON Web Token (JWT)
A string representing a set of claims as a JSON object that is encoded in a JWS or JWE, enabling the claims to be digitally signed or MACed and/or encrypted.

JWT Claims Set
A JSON object that contains the claims conveyed by the JWT.

Claim
A piece of information asserted about a subject. A claim is represented as a name/value pair consisting of a Claim Name and a Claim Value.

Claim Name
The name portion of a claim representation. A Claim Name is always a string.

Claim Value
The value portion of a claim representation. A Claim Value can be any JSON value.

Nested JWT
A JWT in which nested signing and/or encryption are employed. In Nested JWTs, a JWT is used as the payload or plaintext value of an enclosing JWS or JWE structure, respectively.

Unsecured JWT
A JWT whose claims are not integrity protected or encrypted.

Collision-Resistant Name
A name in a namespace that enables names to be allocated in a manner such that they are highly unlikely to collide with other names. Examples of collision-resistant namespaces include: Domain Names, Object Identifiers (OIDs) as defined in the ITU-T X.660 and X.670 Recommendation series, and Universally Unique IDentifiers (UUIDs) [RFC4122]. When using an administratively delegated namespace, the definer of a name needs to take reasonable precautions to ensure they are in control of the portion of the namespace they use to define the name.

StringOrURI
A JSON string value, with the additional requirement that while arbitrary string values MAY be used, any value containing a ":" character MUST be a URI [RFC3986]. StringOrURI values are compared as case-sensitive strings with no transformations or canonicalizations applied.

NumericDate
A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.

3 JSON Web令牌(JWT)概述

JWT表示一组以JWS和/或JWE结构编码的JSON对象的声明。 这个JSON对象是JWT声明集。 根据RFC 7159 [RFC7159]的第4节,JSON对象由零个或多个名称/值对(或成员)组成,其中名称是字符串,值是任意的JSON值。 这些成员是由JWT代表的声明。 根据RFC 7159 [RFC7159]的第2节,此JSON对象可能在任何JSON值或结构字符之前或之后包含空格和/或换行符。

JWT声明集中的成员名称称为声明名称。 相应的值称为声明值。

JOSE标题的内容描述了应用于JWT声明集的加密操作。 如果JOSE标头用于JWS,则JWT被表示为JWS,声明是数字签名或MACed,JWT声明集是JWS有效载荷。 如果JOSE标头用于JWE,则JWT被表示为JWE,声明被加密,JWT声明集是由JWE加密的明文。 JWT可以封装在另一个JWE或JWS结构中,以创建嵌套的JWT,从而实现嵌套签名和加密。

JWT表示为由句点('.')字符分隔的URL安全部分的序列。 每个部分都包含一个base64url编码的值。 JWT中的部件数量取决于使用JWS Compact Serialization或JWE使用JWE Compact Serialization的结果JWS的表示。

3.1 JWT示例

以下示例JOSE Header声明编码对象是JWT,JWT是使用HMAC SHA-256算法进行MACed的JWS:

{"typ":"JWT",
 "alg":"HS256"}

为了消除上述JSON对象表示中的潜在模糊性,上面的JOSE标头在此示例中使用的实际UTF-8表示的八位字节序列也包含在下面。 (请注意,由于换行符(CRLF对LF)的不同平台表示,行的开始和结束处的不同间距,最后一行是否具有终止换行符,以及其他原因,可能会导致模糊。 在这个例子中,第一行没有前导或者后面的空格,在第一行和第二行之间出现一个CRLF换行符(13,10),第二行有一个前导空格(32),没有尾随空格,最后一行 没有终止换行符。)在此示例中使用JOSE标头的UTF-8表示形式的八位字节(使用JSON数组符号)为:

[123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 
   32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125]

Base64url编码JOSE头的UTF-8表示的八位字节产生这个编码的JOSE标头值:

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9

以下是JWT声明集的示例:

{"iss":"joe",
 "exp":1300819380,
 "http://example.com/is_root":true}

以下八位位组序列是JWT声明集合在此示例中使用的UTF-8表示形式,是JWS有效载荷:

[123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10,
   32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56,
   48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97,
   109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111,
   111, 116, 34, 58, 116, 114, 117, 101, 125]

编码JWS有效载荷的Base64url产生这个编码的JWS有效载荷(仅用于显示目的):

eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly
9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ

使用HMAC SHA-256算法计算编码的JOSE标题的MAC和编码的JWS有效载荷,并以[JWS]中指定的方式对HMAC值进行base64url生成此编码的JWS签名:

dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

按照这个顺序将这些编码部分连接在部件之间的周期('.')字符之间产生这个完整的JWT(仅用于显示目的):

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

该计算在[JWS]的附录A.1中有更详细的说明。 有关加密JWT的示例,请参见附录A.1。

4 JWT 声明

JWT声明集代表一个JSON对象,其成员是JWT传达的声明。 JWT声明集中的声明名称必须是唯一的; JWT解析器必须拒绝具有重复的声明名称的JWT,或者使用JSON语法分析器,该语法仅返回最后一个重复的成员名称,如ECMAScript 5.1 ECMAScript第15.12节(“JSON对象”)中所述。

JWT必须包含被认为有效的一组声明是上下文相关的,超出了本规范的范围。 JWT的具体应用将需要实现以特定方式理解和处理一些声明。 然而,在没有这样的要求的情况下,实现中不了解的所有声明必须被忽略。

有三类JWT索赔名称:注册索赔名称,公开声明名称和私人声明名称。

4.1 注册请求名称

以下声明名称已注册在由10.1节建立的IANA“JSON Web令牌声明”注册表中。 以下定义的所有权利要求都不意味着在所有情况下使用或实施是强制性的,而是为一组有用的,可互操作的索赔提供了起点。 使用JWT的应用程序应该定义使用哪些特定声明,何时需要或可选。 所有的名称都很短,因为JWT的核心目标是使其表现得很紧凑。

4.1.1 "iss" (Issuer) 声明

"iss" (issuer) 请求确定发出JWT的委托人。 这种说法的处理通常是具体的应用。 “iss”值是一个包含StringOrURI值的区分大小写的字符串。 使用此声明是可选的。

4.1.2 " sub" (Subject) 声明

"sub" (Subject)请求确定作为JWT主题的委托人。JWT中的请求通常是关于该主题的陈述。 主体值必须在发行者的上下文中被限定为本地唯一的,或者是全局唯一的。 这种说法的处理通常是具体的应用。 “sub”值是一个包含StringOrURI值的区分大小写的字符串。 使用此声明是可选的。

4.1.3 "aud" (Audience) 声明

"aud" (audience)声明识别JWT所针对的收件人。旨在处理JWT的每个主体都必须在受众声明中确定自己的价值。 如果索赔的主要处理在本声明存在的情况下并未标明“aud”索赔中的值,那么JWT必须被拒绝。 在一般情况下,“aud”值是一个区分大小写的字符串数组,每个字符串都包含一个StringOrURI值。 在JWT有一个观众的特殊情况下,“aud”值可以是包含StringOrURI值的单个区分大小写的字符串。 观众价值观的解释一般是具体的应用。 使用此声明是可选的。

4.1.4 "exp" (Expiration Time)请求

"exp" (expiration time)标识JWT不得接受处理之前或之后的到期时间。处理"exp"请求要求当前日期/时间必须在“exp”索赔中列出的到期日期/时间之前。实施者可能会提供一些小的余地,通常不超过几分钟来解决时钟偏差。 其值必须是包含NumericDate值的数字。 使用此声明是可选的。

4.1.5 "nbf" (Not Before) 请求

"nbf" (not before)请求标识JWT不得接受处理的时间。处理“nbf”请求要求当前日期/时间必须在“nbf”索赔中列出的未来日期/时间之前或之后。实施者可能会提供一些小的余地,通常不超过几分钟来解决时钟偏差。其值必须是包含NumericDate值的数字。 使用此声明是可选的。

4.1.6 "iat" (Issued At)请求

"iat"(issued at)请求确定发布JWT的时间。该索赔可用于确定JWT的年龄。 其值必须是包含NumericDate值的数字。 使用此声明是可选的。

4.1.7 "jti" (JWT ID)请求

"jwi"(JWT ID)请求为JWT提供唯一的标识符。必须以确保相同值被意外分配给不同数据对象的可能性很小的方式来分配标识符值;如果应用程序使用多个发行者,则必须在不同发行者产生的值之间防止冲突。“jti”请求可用于防止JWT重播。“jti”值是区分大小写的字符串。 使用此声明是可选的。

4.2 公开声明名称

4.3 私有声明名称

5 JOSE头

5.1 "typ"(Type)头参数

5.2 "cty"(Content Type)头参数

5.3 复制请求作为头参数

6 无担保的JWT

为了支持JWT内容通过除JWT内的签名和/或加密之外的方式来保护的用例(例如包含JWT的数据结构上的签名),JWT也可以在没有签名或加密的情况下创建。不安全的JWT是使用“alg”头参数值“none”的JWS,并且具有JWA规范[JWA]中定义的JWS签名值的空字符串; 它是一个不安全的JWS,JWT声明集合作为其JWS有效载荷。

6.1 无担保的JWT示例

以下示例JOSE Header声明编码对象是Unsecured JWT:

{"alg":"none"}

Base64url编码JOSE头的UTF-8表示的八位字节产生这个编码的JOSE标头值:

eyJhbGciOiJub25lIn0

以下是JWT声明集的示例:

     {"iss":"joe",
      "exp":1300819380,
      "http://example.com/is_root":true}

Base64url编码JWT声明集合的UTF-8表示形式的八位字节产生此编码的JWS有效载荷(仅用于显示目的)

     eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
     cGxlLmNvbS9pc19yb290Ijp0cnVlfQ

编码的JWS签名是空字符串。

按照这个顺序将这些编码部分连接在部件之间的周期('.')字符之间产生这个完整的JWT(仅用于显示目的)

     eyJhbGciOiJub25lIn0
     .
     eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
     cGxlLmNvbS9pc19yb290Ijp0cnVlfQ
     .

7 创建和验证JWT

7.1 创建JWT

要创建JWT,执行以下步骤。 在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。

  1. 创建包含所需声明的JWT声明集。 注意,在表示中明确允许空格,并且在编码之前不需要执行规范化。
  2. 让消息成为JWT声明集的UTF-8表示的八位字节。
  3. 创建一个包含所需的头参数集的JOSE头。 JWT必须符合[JWS]或[JWE]规范。 注意,在表示中明确允许空格,并且在编码之前不需要执行规范化。
  4. 根据JWT是JWS还是JWE,有两种情况:
    • 如果JWT是JWS,则使用Message作为JWS有效负载创建JWS; 必须遵循用于创建JWS的[JWS]中指定的所有步骤。
    • 否则,如果JWT是JWE,则使用Message作为JWE的明文创建一个JWE; 必须遵循[JWE]中为创建JWE而指定的所有步骤。
  5. 如果将执行嵌套签名或加密操作,请将消息作为JWS或JWE,并使用该步骤中创建的新JOSE头中的“cty”(内容类型)值“JWT”返回到步骤3。
  6. 否则,让JWT成为JWS或JWE。

7.2 验证JWT

验证JWT时,执行以下步骤。 在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。 如果任何列出的步骤失败,则JWT必须被拒绝 - 也就是被应用程序视为无效输入。

  1. 验证JWT是否包含至少一个句点('.')。

  2. 让编码的JOSE标题在第一个('.')字符之前成为JWT的一部分。

  3. Base64url解码编码的JOSE标题,遵循不使用换行符,空格或其他附加字符的限制。

  4. 验证结果八位字节序列是符合RFC 7159 RFC7159的完全有效的JSON对象的UTF-8编码表示形式。 让JOSE Header成为这个JSON对象。

  5. 验证生成的JOSE头只包含其语法和语义都被理解和支持的参数和值,或者在不明白的情况下被指定为被忽略。

  6. 使用JWE第9节中描述的任何方法确定JWT是JWS还是JWE。

  7. 根据JWT是JWS还是JWE,有两种情况:

    • 如果JWT是JWS,请按照JWS中指定的步骤验证JWS。 让消息是base64url解码JWS有效载荷的结果。
    • 否则,如果JWT是JWE,请按照JWE中指定的步骤验证JWE。 让消息成为明文。
  8. 如果JOSE标头包含“cty”(内容类型)值“JWT”,则该消息是作为嵌套签名或加密操作主题的JWT。 在这种情况下,返回步骤1,使用Message作为JWT。

  9. 否则,base64url解码消息,遵循没有换行符,空格或其他附加字符的限制。

  10. 验证结果八位字节序列是符合RFC 7159 [RFC7159]的完全有效的JSON对象的UTF-8编码表示形式。 让JWT声明集成为这个JSON对象。

最后,请注意,在给定的上下文中可以使用哪种算法。 即使JWT可以成功验证,除非JWT中使用的算法可以被应用程序所接受,否则它应该拒绝JWT。

7.3 字符串比较规则

处理JWT不可避免地需要将已知字符串与JSON对象中的成员和值进行比较。 例如,在检查算法的情况下,将根据JOSE标头中的成员名称检查Unicode UNICODE字符串编码“alg”,以查看是否存在匹配的标题参数名称。

RFC 7159第8.3节描述了进行成员名称比较的JSON规则。 由于执行的唯一的字符串比较操作是相等和不等式,因此可以使用相同的规则来比较成员名称和成员值与已知字符串的比较。

这些比较规则必须用于所有的JSON字符串比较,除非成员的定义显式地调用不同的比较规则用于该成员值。 在本规范中,只有“typ”和“cty”成员值不使用这些比较规则。

一些应用程序可能包含区分大小写的值中的不区分大小写的信息,例如将DNS名称作为“iss”(发行者)声明值的一部分。 在这些情况下,应用程序可能需要为规范情况定义一个约定,用于表示不区分大小写的部分,例如,如果多个方可能需要生成相同的值才能进行比较,比如缩小它们。 (但是,如果所有其他方都消费生产者逐字排出的价值,而不尝试将其与独立产生的价值进行比较,则生产者使用的情况并不重要。)

8 实施要求

本节定义了本规范的哪些算法和功能是必须实现的。 使用此规范的应用程序可以对其使用的实现施加额外的要求。 例如,一个应用程序可能需要支持加密的JWT和嵌套JWT,而另一个应用程序可能需要使用P-256曲线和SHA-256散列算法(“ES256”)来支持使用椭圆曲线数字签名算法(ECDSA)签名JWT。

在JSON Web算法JWA中指定的签名和MAC算法中,只有HMAC SHA-256(“HS256”)和“none”必须通过符合JWT实现来实现。 推荐实现还使用SHA-256哈希算法(“RS256”)和使用P-256曲线和SHA-256哈希算法(“ES256”)的ECDSA支持RSASSA-PKCS1-v1_5。 支持其他算法和密钥大小是可选的。

支持加密的JWT是可选的。 如果一个实现提供加密功能,在JWA中指定的加密算法中,只有具有2048位密钥(“RSA1_5”)的RSAES-PKCS1-v1_5,具有128位和256位密钥的AES密钥包(“A128KW”和 “A256KW”),使用AES-CBC和HMAC SHA-2(“A128CBC-HS256”和“A256CBC-HS512”)的复合认证加密算法必须通过一致的实现来实现。 建议实现还支持使用椭圆曲线Diffie-Hellman临时静态(ECDH-ES)来同意用于包装内容加密密钥(“ECDH-ES + A128KW”和“ECDH-ES + A256KW”)的密钥,以及 具有128位和256位密钥(“A128GCM”和“A256GCM”)的伽罗瓦/计数器模式(GCM)的AES。 支持其他算法和密钥大小是可选的。

对嵌套JWT的支持是可选的。

9 声明Content是JWT的URI

该规范注册URN“urn:ietf:params:oauth:token-type:jwt”供应用程序使用,该应用程序使用URI声明内容类型(而不是例如媒体类型)来表示所引用的内容是JWT。

10 IANA注意事项

10.1 JSON Web令牌声明注册表

本节为JWT声明名称建立IANA“JSON Web令牌声明”注册表。 注册表记录了声明名称和对定义它的规范的引用。 本节记录第4.1节中定义的声明名称。

根据一个或多个指定专家的建议,在jwt-reg-review@ietf.org邮件列表上进行为期三周的审查期后,值将以规范要求RFC5226进行注册。 然而,为了允许在出版之前分配价值,指定专家一旦确信这样的规范将被公布,就可以批准注册。

发送到邮件列表进行审查的注册请求应使用适当的主题(例如“请求注册声明:示例”)。

在审查期内,指定专家将批准或拒绝注册请求,将此决定通知审查清单和IANA。 拒绝应该包括解释,如果适用的话,应该提出如何使请求成功的建议。 长达21天以上未注册的注册请求可以通过IESG的注意(使用iesg@ietf.org邮件列表)进行解决。

指定专家应适用的标准包括确定提议的注册是否与现有功能重复,是否可能具有一般适用性,还是仅对单个应用程序有用,以及注册描述是否明确。

IANA只能接受指定专家的注册表更新,并应将所有注册请求引导到审阅邮件列表。

建议指定多名指定专家,使用本规范能够代表不同应用的观点,以便能够对注册决策进行广泛的了解。

如果注册决定可能被认为是为特定专家造成利益冲突的情况,该专家应该依照其他专家的判断。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容