Apache Ranger及Hive權(quán)限控制

一益缎、Ranger概述

1.Ranger簡介

Apache Ranger提供一個(gè)集中式安全管理框架, 并解決授權(quán)和審計(jì)。它可以對(duì)Hadoop生態(tài)的組件如HDFS义图、Yarn、Hive、Hbase等進(jìn)行細(xì)粒度的數(shù)據(jù)訪問控制。通過操作Ranger控制臺(tái),管理員可以輕松的通過配置策略來控制用戶訪問權(quán)限。

本文章介紹Ranger與Hive集成過程,與使用方法

2.Ranger包含以下組件

  • Ranger Admin 用戶管理策略乞榨,提供WebUI和RestFul接口
  • Ranger UserSync 用于將Unix系統(tǒng)或LDAP用戶/組同步到RangerAdmin
  • Ranger TagSync 同步Atlas中的Tag信息
  • Ranger KMS
000.jpg

3.Ranger依賴的組件:

  • JDK 運(yùn)行RangerAdmin RangerKMS
  • RDBMS 1.存儲(chǔ)授權(quán)策略 2.存儲(chǔ)Ranger 用戶/組 3.存儲(chǔ)審核日志
  • Solr(可選) 存儲(chǔ)審核日志
  • HDFS(可選) 存儲(chǔ)審核日志
  • Kerberos(可選) 確保所有請(qǐng)求都被認(rèn)證

4.目前Ranger0.7支持的Plugin

  • HDFS
  • YARN
  • SOLR
  • ATLAS
  • HBASE
  • KNOX
  • KAFKA
  • HIVE
  • STORM
  • NIFI

二、Ranger編譯安裝

說明: Ranger可以在Ambari上直接安裝当娱。開啟AmbariHivePlugin也可以直接在頁面上操作吃既。
但如果跟ApacheHive集成的話,需要先編譯出ApacheRanger的HivePlugin來

1.Apache Ranger編譯

#Install maven git gcc mysql
git clone https://github.com/apache/ranger.git
cd ranger
git checkout release-ranger-0.7.1
mvn clean compile package assembly:assembly install -DskipTests
ls target

2.通過Ambari安裝Ranger

  • 前置條件:
  • 1.必須有 MySQL/Oracle/Postgres/MSSQL/SQL Anywhere Server 數(shù)據(jù)庫實(shí)例
  • 2.在RangerAdmin主機(jī)上 必須安裝DB Client
  • 3.確保DB Admin用戶可以再其他機(jī)器上登陸(用來創(chuàng)建ranger用戶)
  • 4.執(zhí)行下面的命令 導(dǎo)入JDBC驅(qū)動(dòng) ambari-server setup --jdbc-db={database-type} --jdbc-driver={/jdbc/driver/path}
#導(dǎo)入JDBC驅(qū)動(dòng):
#(MySQL JDBC Driver Jar包下載頁面:https://dev.mysql.com/downloads/connector/j/5.0.html)
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.0.8.tar.gz
tar -zxvf mysql-connector-java-5.0.8.tar.gz
ambari-server setup --jdbc-db=mysql --jdbc-driver=mysql-connector-java-5.0.8/mysql-connector-java-5.0.8-bin.jar

3.安裝RangerHivePlugin

登陸RangerAdmin: http://l-node1.data.beta.cn0:6080

#AmbariHive可直接在Ambari頁面上操作
#ApacheHive的話 需要執(zhí)行以下命令:

# 1.拷貝RangerHivePlugin安裝包
cp target/ranger-0.7.1-hive-plugin.tar.gz /usr/apache
tar -zxvf /usr/apache/ranger-0.7.1-hive-plugin.tar.gz

# 2.編輯install.properties文件
#編輯POLICY_MGR_URL 指向RangerAdmin 例如 POLICY_MGR_URL=http://l-node1.data.beta.cn0:6080
#編輯REPOSITORY_NAME 要與RangerAdmin中ServiceName配置一致 例如 REPOSITORY_NAME=hivebeta
vim /usr/apache/ranger-0.7.1-hive-plugin/install.properties

# 3.配置JAVA_HOME HIVE_HOME 環(huán)境變量
echo "export JAVA_HOME=/usr/java/jdk1.8.0_141" >> /etc/bashrc
echo "export HIVE_HOME=/usr/apache/hive" >> /etc/bashrc
source /etc/bashrc

# 4.開啟plugin
sudo sh /usr/apache/ranger-0.7.1-hive-plugin/enable-hive-plugin.sh
#顯示Ranger Plugin for hive has been enabled. Please restart hive to ensure that changes are effective.即成功

# 5.重啟HiveServer

4.RangerAdmin上面配置要管理的HiveServer實(shí)例

001.png

002.png

三跨细、Ranger Hive權(quán)限控制

1.準(zhǔn)備測(cè)試數(shù)據(jù)

點(diǎn)擊hivebeta 開始Hive權(quán)限控制

003.png

根據(jù)我們剛才的配置,hive用戶擁有all權(quán)限

使用beeline登陸
[hive@l-node3 hive]$ bin/beeline
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/apache/apache-hive-2.3.0-bin/lib/log4j-slf4j-impl-2.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/hdp/2.6.1.0-129/hadoop/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
Beeline version 2.3.0 by Apache Hive
beeline> !connect jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2_ha
Connecting to jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2_ha
Enter username for jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/: hive
Enter password for jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/:
17/08/03 11:49:28 [main]: INFO jdbc.HiveConnection: Connected to l-node5.data.beta.cn0:10000
Connected to: Apache Hive (version 2.3.0)
Driver: Hive JDBC (version 2.3.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ

#創(chuàng)建ranger測(cè)試庫
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> create database ranger_test_db;
No rows affected (0.259 seconds)
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> use ranger_test_db;
No rows affected (0.114 seconds)

#創(chuàng)建測(cè)試表
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> CREATE TABLE t_user
. . . . . . . . . . . . . . . . . . . . . . .> (name STRING,phone STRING)
. . . . . . . . . . . . . . . . . . . . . . .> ROW FORMAT DELIMITED
. . . . . . . . . . . . . . . . . . . . . . .> FIELDS TERMINATED BY '\t'
. . . . . . . . . . . . . . . . . . . . . . .> STORED AS TEXTFILE;
No rows affected (0.317 seconds)
# 表數(shù)據(jù)
[hive@l-node3 hive]$ hadoop fs -cat /tmp/t_user.data
meizi   18518760001
xuaner  18518760002
afa 18518760003
hanze   18518760004
xupeng  18518760005
xiaofeng    18518760006
shuoshuo    18518760007
# 導(dǎo)入數(shù)據(jù)
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> LOAD DATA INPATH '/tmp/t_user.data' INTO TABLE t_user;
No rows affected (0.523 seconds)

#查詢成功
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> select * from t_user;
+--------------+---------------+
| t_user.name  | t_user.phone  |
+--------------+---------------+
| meizi        | 18518760001   |
| xuaner       | 18518760002   |
| afa          | 18518760003   |
| hanze        | 18518760004   |
| xupeng       | 18518760005   |
| xiaofeng     | 18518760006   |
| shuoshuo     | 18518760007   |
+--------------+---------------+
7 rows selected (0.11 seconds)

2.HiveAccess(對(duì)庫鹦倚、表、列的授權(quán))

# 在Ranger UserSync機(jī)器上創(chuàng)建測(cè)試用戶rangeruser1
[root@l-node1 ~]# useradd rangeruser1
# 測(cè)試未授權(quán)的用戶
[hive@l-node3 hive]$ bin/beeline
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/apache/apache-hive-2.3.0-bin/lib/log4j-slf4j-impl-2.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/hdp/2.6.1.0-129/hadoop/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
Beeline version 2.3.0 by Apache Hive
beeline> !connect jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2_ha
Connecting to jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2_ha

#使用rangeruser1用戶登陸
Enter username for jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/: rangeruser1
Enter password for jdbc:hive2://l-node1.data.beta.cn0:2181,l-node2.data.beta.cn0:2181,l-node3.data.beta.cn0:2181/:
17/08/03 12:30:58 [main]: INFO jdbc.HiveConnection: Connected to l-node5.data.beta.cn0:10000
Connected to: Apache Hive (version 2.3.0)
Driver: Hive JDBC (version 2.3.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ

# use db; select table; 等訪問全部被拒絕
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> use ranger_test_db;
Error: Error while compiling statement: FAILED: HiveAccessControlException Permission denied: user [rangeruser1] does not have [USE] privilege on [ranger_test_db] (state=42000,code=40000)
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> select * from ranger_test_db.t_user;
Error: Error while compiling statement: FAILED: HiveAccessControlException Permission denied: user [rangeruser1] does not have [SELECT] privilege on [ranger_test_db/t_user/*] (state=42000,code=40000)

給rangeruser1用戶授權(quán)

點(diǎn)擊Add New Policy給rangeruser1用戶授予ranger_test_db.t_user.* select權(quán)限

004.png
#select成功
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> use ranger_test_db;
No rows affected (0.127 seconds)
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> select * from t_user;
+--------------+---------------+
| t_user.name  | t_user.phone  |
+--------------+---------------+
| meizi        | 18518760001   |
| xuaner       | 18518760002   |
| afa          | 18518760003   |
| hanze        | 18518760004   |
| xupeng       | 18518760005   |
| xiaofeng     | 18518760006   |
| shuoshuo     | 18518760007   |
+--------------+---------------+
7 rows selected (0.12 seconds)

#刪除表 被拒絕
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> drop table t_user;
Error: Error while compiling statement: FAILED: HiveAccessControlException Permission denied: user [rangeruser1] does not have [DROP] privilege on [ranger_test_db/t_user] (state=42000,code=40000)

#創(chuàng)建表 被拒絕
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> CREATE TABLE t_user2
. . . . . . . . . . . . . . . . . . . . . . .> (name STRING,phone STRING)
. . . . . . . . . . . . . . . . . . . . . . .> ROW FORMAT DELIMITED
. . . . . . . . . . . . . . . . . . . . . . .> FIELDS TERMINATED BY '\t'
. . . . . . . . . . . . . . . . . . . . . . .> STORED AS TEXTFILE;
Error: Error while compiling statement: FAILED: HiveAccessControlException Permission denied: user [rangeruser1] does not have [CREATE] privilege on [ranger_test_db/t_user2] (state=42000,code=40000)

Delegate Admin(委托管理員)說明: 如果一個(gè)Condition中的 用戶/組 為Delegate Admin冀惭,那么該 用戶/組 可以修改上面resource的權(quán)限 并可以把此resource授權(quán)給其他人

也可以使用SQL進(jìn)行授權(quán)(授權(quán)過的記錄同樣會(huì)顯示在RangerAdmin上):
GRANT SELECT ON TABLE ranger_test_db.t_user TO USER fengjie;

3.Masking(動(dòng)態(tài)列屏蔽)

動(dòng)態(tài)列屏蔽: 可以將一列數(shù)據(jù)進(jìn)行屏蔽操作 如哈希震叙、加密掀鹅、打馬賽克等

添加一個(gè)Masking Policy

005.png

006.png

Select Masking Option里面填Mask的選項(xiàng),默認(rèn)有: 顯示前4位媒楼、顯示后4位乐尊、哈希、Null值划址、日期類型僅顯示年等扔嵌。我們這里使用Custom自定義,
其實(shí)就是寫Select子句 可以根據(jù)邏輯自己實(shí)現(xiàn)夺颤,也可使用UDF痢缎。本例中我們使用concat(substr(phone,1,7),'****')將手機(jī)號(hào)的后四位屏蔽掉

0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> select * from t_user;
+--------------+---------------+
| t_user.name  | t_user.phone  |
+--------------+---------------+
| meizi        | 1851876****   |
| xuaner       | 1851876****   |
| afa          | 1851876****   |
| hanze        | 1851876****   |
| xupeng       | 1851876****   |
| xiaofeng     | 1851876****   |
| shuoshuo     | 1851876****   |
+--------------+---------------+
7 rows selected (0.173 seconds)

4.Row Level Filter(行級(jí)別過濾)

行級(jí)別過濾: 可以過濾掉行數(shù)據(jù)。比如訂單表,北京的員工僅允許看北京的訂單數(shù)據(jù),其他地區(qū)的數(shù)據(jù)被強(qiáng)制過濾掉

添加一個(gè)Row Level Filter Policy

007.png

008.png

Row Level Filter里面填Filter的過濾規(guī)則世澜,其實(shí)就是寫Where子句独旷。本例中我們使用name <> 'hanze'將 name為'hanze'的用戶過濾掉

#hanze用戶已經(jīng)被過濾掉,不顯示在結(jié)果中了
0: jdbc:hive2://l-node1.data.beta.cn0:2181,l-> select * from t_user;
+--------------+---------------+
| t_user.name  | t_user.phone  |
+--------------+---------------+
| meizi        | 1851876****   |
| xuaner       | 1851876****   |
| afa          | 1851876****   |
| xupeng       | 1851876****   |
| xiaofeng     | 1851876****   |
| shuoshuo     | 1851876****   |
+--------------+---------------+
6 rows selected (0.164 seconds)

四寥裂、基于TAG的權(quán)限控制

Apache Ranger可以和Apache Atlas(數(shù)據(jù)治理,元數(shù)據(jù)倉儲(chǔ))組件一起使用势告,它可以定義一種基于標(biāo)簽的安全服務(wù),通過使用標(biāo)簽對(duì)文件和數(shù)據(jù)資產(chǎn)進(jìn)行分類抚恒,并控制用戶和用戶組對(duì)一系列標(biāo)簽的訪問。

Apache Atlas里面可以對(duì)資源打Tag络拌。打了Tag后 我們可以在這里根據(jù)Tag來控制權(quán)限
(注意:因需要集成Atlas 此功能暫未驗(yàn)證)

1.添加TagService

009.png

010.png

2.添加TagPolicy

011.png

012.png

上圖的Policy俭驮,實(shí)現(xiàn)了這樣的場景:
產(chǎn)品組(product)可以訪問帶"TAG"標(biāo)簽的資源; 但實(shí)習(xí)生(intern)不靠譜 實(shí)習(xí)生沒有訪問權(quán)限; 但因?qū)嵙?xí)生中的meizi表現(xiàn)突出 給他賦予訪問權(quán)限

3.授權(quán)流程:

013.png

先檢查基于Tag的權(quán)限是否拒絕,如果拒絕的話,報(bào)錯(cuò)退出春贸。
如果不拒絕,再檢查基于Resource的權(quán)限拒不拒絕混萝。
如果不拒絕,再檢查Tag的權(quán)限允不允許,Resource的權(quán)限允不允許。

五萍恕、Audit審計(jì)記錄

1.Access

此頁面記錄每次授權(quán)的信息 包括策略id逸嘀、時(shí)間、訪問用戶允粤、訪問的資源崭倘、訪問的類型、授權(quán)結(jié)果等信息类垫∷竟猓可以根據(jù)條件進(jìn)行搜索
開啟此功能需要先安裝Solr

014.png

2.Admin

此頁面記錄對(duì)策略的操作

015.png

3.Login Sessions

此頁面記錄登陸RangerAdmin的操作

016.png

4.Plugins

記錄Plugins的同步策略

017.png

5.Pugins Status

Plugin的狀態(tài)

018.png

六、RestAPI

以上在RangerAdminWeb上操作的東西 都可以在RestAPI里面操作悉患。
比如 添加服務(wù)残家、更新服務(wù)、刪除服務(wù)售躁、搜索服務(wù)坞淮、獲取策略茴晋、創(chuàng)建策略、更新策略回窘、刪除策略诺擅、搜索策略等

API name                Create Policy
Request Type            POST
Request URL             service/public/v2/api/policy
Request Parameters      Application/json

Hive Example:
{
 "policyName": "FinancePolicy",
 "databases": "finance,hr",
 "tables": "invoices,emps",
 "columns": "amt, emp_id",
 "udfs": "",
 "description": "Hive Policy",
 "repositoryName": "hivedev",
 "repositoryType": "hive",
 "tableType": "Exclusion",
 "columnType": "Inclusion",
 "isEnabled": true,
 "isAuditEnabled": true,
 "permMapList": [
 {
 "userList": [
 "john",
 "andrew"
 ],
 "permList": [
 "Write",
 "Admin"
 ]
 },
 {
 "userList": [
 "hr"
 ],
 "groupList": [
 "admin"
 ],
 "permList": [
 "Read",
 "Write",
 "Admin"
 ]
 }
 ]
}

參考文檔

Apache Ranger Installation

Apache Ranger User Guide

Hortonworks HDP doc

HDFS + Ranger

Ranger PPT

Ranger + Atlas PPT

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毫玖,隨后出現(xiàn)的幾起案子掀虎,更是在濱河造成了極大的恐慌,老刑警劉巖付枫,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烹玉,死亡現(xiàn)場離奇詭異,居然都是意外死亡阐滩,警方通過查閱死者的電腦和手機(jī)二打,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掂榔,“玉大人继效,你說我怎么就攤上這事∽盎瘢” “怎么了瑞信?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長穴豫。 經(jīng)常有香客問我凡简,道長,這世上最難降的妖魔是什么精肃? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任秤涩,我火速辦了婚禮,結(jié)果婚禮上司抱,老公的妹妹穿的比我還像新娘筐眷。我一直安慰自己,他們只是感情好习柠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布匀谣。 她就那樣靜靜地躺著,像睡著了一般资溃。 火紅的嫁衣襯著肌膚如雪振定。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天肉拓,我揣著相機(jī)與錄音后频,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卑惜,可吹牛的內(nèi)容都是我干的膏执。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼露久,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼更米!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毫痕,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤征峦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后消请,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栏笆,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年臊泰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛉加。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缸逃,死狀恐怖针饥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情需频,我是刑警寧澤丁眼,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站昭殉,受9級(jí)特大地震影響苞七,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饲化,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吗伤。 院中可真熱鬧吃靠,春花似錦、人聲如沸足淆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巧号。三九已至族奢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丹鸿,已是汗流浹背越走。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人廊敌。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓铜跑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骡澈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锅纺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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