shiro實(shí)現(xiàn)授權(quán)-注解方式

一個(gè)用戶對(duì)應(yīng)多個(gè)角色
一個(gè)角色對(duì)應(yīng)多個(gè)權(quán)限
本案例的權(quán)限體現(xiàn)在菜單對(duì)應(yīng)的permission(授權(quán)標(biāo)識(shí))上夕土,權(quán)限檢查會(huì)檢查對(duì)應(yīng)菜單的permission(授權(quán)標(biāo)識(shí))

menu

roles

roles_menus

sys_users

sys_users_roles
USE `shop`;

/*Table structure for table `menus` */

DROP TABLE IF EXISTS `menus`;

CREATE TABLE `menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  `type` int(11) DEFAULT NULL,
  `sort` int(11) DEFAULT NULL,
  `note` varchar(100) DEFAULT NULL,
  `parentId` int(11) DEFAULT NULL,
  `permission` varchar(500) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `updated` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Data for the table `menus` */

insert  into `menus`(`id`,`name`,`url`,`type`,`sort`,`note`,`parentId`,`permission`,`created`,`updated`) values (1,'系統(tǒng)管理','',1,1,'系統(tǒng)管理...',0,'sys:view','2019-09-15 10:17:31','2019-09-21 21:14:27'),(2,'角色管理','role/list',1,2,'角色管理...',1,'sys:role:view','2019-09-15 10:18:04','2019-10-13 23:56:06'),(3,'用戶管理','user/list',1,3,'用戶管理...',1,'sys:user:view','2019-09-21 19:49:36','2019-10-13 23:56:42'),(4,'角色添加','role/saveObject',2,1,'角色添加',2,'sys:role:create','2019-10-13 23:55:45','2019-10-13 23:59:10'),(5,'角色修改','role/updateObject',2,2,'角色修改',2,'sys:role:update','2019-10-13 23:58:28','2019-10-20 14:23:27');

/*Table structure for table `roles` */

DROP TABLE IF EXISTS `roles`;

CREATE TABLE `roles` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `note` varchar(500) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `updated` datetime DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

/*Data for the table `roles` */

insert  into `roles`(`id`,`name`,`note`,`created`,`updated`) values (51,'admin','管理員','2019-09-04 22:15:35','2019-09-04 22:15:35'),(52,'normal','普通用戶','2019-09-04 22:15:47','2019-10-20 14:41:46');

/*Table structure for table `roles_menus` */

DROP TABLE IF EXISTS `roles_menus`;

CREATE TABLE `roles_menus` (
  `role_id` int(11) NOT NULL DEFAULT '0',
  `menu_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`role_id`,`menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `roles_menus` */

insert  into `roles_menus`(`role_id`,`menu_id`) values (51,1),(51,2),(51,3),(51,4),(51,5);

/*Table structure for table `sys_users`   密碼均為123 */

DROP TABLE IF EXISTS `sys_users`;

CREATE TABLE `sys_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` varchar(50) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `mobile` varchar(100) DEFAULT NULL,
  `valid` tinyint(4) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `updated` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

/*Data for the table `sys_users` */

insert  into `sys_users`(`id`,`username`,`password`,`salt`,`email`,`mobile`,`valid`,`created`,`updated`) values (1,'zhangsan','b89a1238af16bf30c5cc572f08c60e82','0ca5b031-1cc5-40e8-94b6-e577e2b78f52','a@qq.com','15300018956',1,'2019-09-04 00:03:37','2019-10-13 23:11:56'),(2,'lisi','29e95d825f49af77e90449b62effaaf8','66d7c441-2b3e-4343-8c9e-054e9e580dfe','b@qq.com','15300018923',1,'2019-09-04 00:03:41','2019-10-13 23:11:37'),(3,'test','269925a0fcd19ee9749715d66538cb37','08c01cbc-773a-4dda-a83d-6db7ea0f695c','2@qq.com','15300018569',1,'2019-09-04 23:12:58','2019-10-13 23:11:47'),(4,'alpcer','e4c943a82b9752a21c01501db29998bb','377cc328-88ce-4534-b4a0-ff2914ab6155','a@qq.com','15300028652',1,'2019-09-04 23:31:56','2019-10-13 23:12:41'),(5,'mjp','d503597b4f73c4c25eeb15f5d44c8411','5dcc5134-793e-4765-8383-fe4b1d157cba','b@163.com','15300018562',1,'2019-09-06 23:06:15','2019-10-13 23:11:17'),(6,'wx','420a1a4ae0f5565d27004af508ee270d','b16daf59-cbc5-48c6-a91f-2a5f481c90bb','b@163.com','15300018562',1,'2019-09-06 23:07:19','2019-10-13 22:52:20'),(7,'ww','52a1df05ff427c0007791b978d2b9981','025da5d4-9a4b-4ea1-aed4-cca185fab4f9','b@163.com','15300018562',1,'2019-09-06 23:09:37','2019-10-13 23:07:04'),(8,'sy_test','9ec076534b0039e1f4bd8637c2d8a69e','c95f38ce-9ce4-4775-9511-558bdf0b7475','b@163.com','15300018562',1,'2019-09-06 23:12:13','2019-10-13 23:10:54'),(9,'alice','7fbc8843e04e00f80f2108de071e7a3a','420557e2-d1c0-4ac4-b8fe-2e7dfb969211','b@qq.com','15300018923',1,'2019-09-13 20:56:53','2019-10-13 23:10:47'),(10,'dom','89f7cae0dd7727abb5a99c3a9a405ceb','8a56660a-c1d3-46c4-9514-f3317484c4fc','eeeb@163.com','15300018562',1,'2019-09-13 20:57:28','2019-10-13 23:10:38'),(11,'John','6c1574fbb2ffe9da7147b3540454b1da','21b1f675-a36e-41d8-b021-23ec8925b72c','b@163.com','15300018562',1,'2019-09-13 20:58:07','2019-10-13 23:10:30'),(12,'wangnan','04f3f1cce625d30b37ee39911c10c88a','be21abb3-dfde-44d4-80bf-4d9adfafee21','1223@qq.com','66666',1,'2019-09-13 21:02:14','2019-10-13 23:08:54'),(13,'David','05a629f9a12a115384c2f2ea91f6470e','17520f66-4f75-48f1-b9a7-843e7a2df944','b@163.com','15300018562',1,'2019-09-13 21:03:21','2019-10-13 23:08:46'),(14,'bell','c78c8465d7ca0e12a224d4ea11cc6845','dc56cbde-694e-45eb-af4b-f9deba147a99','111@qq.com','110',1,'2019-09-13 21:49:33','2019-10-13 23:08:36'),(15,'wangbaoqiang','841dc36cb55c56bb0d690b87035adafe','4a0dd0d4-8757-4c37-9194-15d7d3bd858c','wang@qq.com','15300018952',1,'2019-10-06 12:58:22','2019-10-13 23:10:11'),(16,'zhanglei','6efcf4e9dec2eb42af7479985f6745c2','9437c6bb-9c12-403b-80b9-e05611fc40ba','4@qq.com','2',1,'2019-10-06 12:59:47','2019-10-20 14:28:56');

/*Table structure for table `sys_users_roles` */

DROP TABLE IF EXISTS `sys_users_roles`;

CREATE TABLE `sys_users_roles` (
  `user_id` int(11) NOT NULL DEFAULT '0',
  `role_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `sys_users_roles` */

insert  into `sys_users_roles`(`user_id`,`role_id`) values (1,51),(2,52),(3,51),(4,52),(5,52),(6,52),(7,51),(7,52),(8,52),(9,51),(9,52),(10,51),(11,51),(11,52),(12,51),(13,52),(14,51),(14,52),(15,51),(16,51);

pom.xml

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.3.2</version>
        </dependency>

核心代碼-權(quán)限有可能重復(fù)绕沈,所以放到set集合蚪燕,放之前先排除空串

/**
     * 授權(quán)檢測(cè)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUser user=(SysUser) SecurityUtils.getSubject().getSession().getAttribute("user");
        //根據(jù)用戶信息獲取用戶權(quán)限
        List<String> list=sysUserDao.findUserPermissions(user.getId());
        //去除重復(fù)的權(quán)限
        HashSet<String> set = new HashSet<>();
        for(String p:list){
            if(!StringUtils.isEmpty(p)){
                set.add(p);
            }
        }
        System.out.println("permissions= "+set);
        //封裝用戶權(quán)限
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.setStringPermissions(set);
        return info;
    }
package com.school.service.realm;

import java.util.HashSet;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;
import com.school.dao.SysUserDao;
import com.school.entity.SysUser;
/**
 *通過realm這個(gè)領(lǐng)域?qū)ο髮?duì)認(rèn)證領(lǐng)域和授權(quán)領(lǐng)域信息進(jìn)行檢測(cè)
 */
@Service
public class ShiroUserRealm extends AuthorizingRealm {
    @Autowired
    SysUserDao sysUserDao;

    /**
     * 授權(quán)檢測(cè)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUser user=(SysUser) SecurityUtils.getSubject().getSession().getAttribute("user");
        //根據(jù)用戶信息獲取用戶權(quán)限
        List<String> list=sysUserDao.findUserPermissions(user.getId());
        //去除重復(fù)的權(quán)限
        HashSet<String> set = new HashSet<>();
        for(String p:list){
            if(!StringUtils.isEmpty(p)){
                set.add(p);
            }
        }
        System.out.println("permissions= "+set);
        //封裝用戶權(quán)限
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.setStringPermissions(set);
        return info;
    }

    /**
     * 認(rèn)證檢測(cè)
     * 檢測(cè)用戶身份是否存在剩膘,密碼是否正確
     * subject.login(token)->
     * SecurityManager->
     * Authentication->
     * ShiroUserRealm->
     * ShiroUserRealm.Authentication
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken=(UsernamePasswordToken)token;
        //獲取用戶名
        String username = upToken.getUsername();
        //根據(jù)用戶名查找用戶對(duì)象
        SysUser user = sysUserDao.findObjectByUserName(username);
        //初始化SimpleAuthenticationInfo對(duì)象
        ByteSource saltSource = ByteSource.Util.bytes(user.getSalt().getBytes());
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
                user.getUsername(),//用戶身份
                user.getPassword(), //已加密 的密碼
                saltSource,//鹽值對(duì)應(yīng)的byteSource
                getName());//realm的名字
        //存儲(chǔ)用戶信息
        SecurityUtils.getSubject().getSession().setAttribute("user", user);
        return info;
    }

}

web.xml

    <!--配置SpringMVC前端控制器 -->
    <!--配置shiro -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>shiroFilter</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

shiro-configs.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="  
       http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd  
       http://www.springframework.org/schema/mvc   
       http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd   
       http://www.springframework.org/schema/tx   
       http://www.springframework.org/schema/tx/spring-tx-4.3.xsd   
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
       http://www.springframework.org/schema/util 
       http://www.springframework.org/schema/util/spring-util-4.3.xsd
       http://www.springframework.org/schema/data/jpa 
       http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <bean id="userRealm" class="com.school.service.realm.ShiroUserRealm">
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5" />
            </bean>
        </property>
    </bean>
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="loginUrl"  value="/login"/>
        <property name="securityManager" ref="securityManager"></property>
        <property name="filterChainDefinitions">
            <value>
                /bootstrap/**=anon
                /build/**=anon
                /dist/**=anon
                /document/**=anon
                /font-awesome/**=anon
                /ionicons/**=anon
                /layer/**=anon
                /pages/**=anon
                /plugins/**=anon
                /treegrid/**=anon
                /ztree/**=anon
                /doLogin=anon
                /doLogout=logout
                /**=authc
            </value>
        </property>
    </bean>
    <!-- 配置Shiro中的SecurityManager -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRealm"></property>
    </bean>
    
    <!-- 配置bean對(duì)象的生命周期管理 (可以自動(dòng)地調(diào)用配置在springIoc容器中shiro-bean的生命周期方法)-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 啟用shiro注解權(quán)限檢查 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    depends-on="lifecycleBeanPostProcessor"/>
    <!-- 配置授權(quán)屬性 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="SecurityManager" ref="securityManager"></property>
    </bean>
</beans>

這幾項(xiàng)就是權(quán)限檢查的配置

    <!-- 配置bean對(duì)象的生命周期管理 (可以自動(dòng)地調(diào)用配置在springIoc容器中shiro-bean的生命周期方法)-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 啟用shiro注解權(quán)限檢查 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    depends-on="lifecycleBeanPostProcessor"/>
    <!-- 配置授權(quán)屬性 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="SecurityManager" ref="securityManager"></property>
    </bean>
</beans>

在需要做權(quán)限檢查的地方加注解,比如 @RequiresPermissions("sys:role:update")
在用戶進(jìn)行角色更新的時(shí)候爪飘,進(jìn)行權(quán)限檢查

    @RequiresPermissions("sys:role:update")
    @RequestMapping("/updateObject")
    @ResponseBody
    public JsonResult updateObject(Role entity){
        roleService.updateObject(entity); 
        return new JsonResult(1,"update ok");
    }

因?yàn)闆]有權(quán)限會(huì)拋異常哆档,所以在異常處理類可做如下操作

else if(e instanceof UnauthorizedException){
            msg="權(quán)限不足!";
        }

完整代碼如下

package com.school.common.controller;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.school.common.exception.ServiceException;
import com.school.common.vo.JsonResult;

@ControllerAdvice
public class ControllerExceptionHandler {
    /**
     * @ExceptionHandler 用于描述這個(gè)方法能夠處理的異常
     * @param e
     */
    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public JsonResult handleServiceException(ServiceException e){
        String msg=e.getMessage();
        System.out.println(msg);
        return new JsonResult(0,msg);
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public JsonResult handleServiceException(RuntimeException e){
        String msg=e.getMessage();
        if(e instanceof IncorrectCredentialsException){
            msg="密碼不正確!";
        }
        else if(e instanceof AuthenticationException){
            msg="用戶名不存在!";
        }
        else if(e instanceof UnauthorizedException){
            msg="權(quán)限不足!";
        }
        System.out.println(msg);
        return new JsonResult(0,msg);
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市淆两,隨后出現(xiàn)的幾起案子断箫,更是在濱河造成了極大的恐慌,老刑警劉巖秋冰,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仲义,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡剑勾,警方通過查閱死者的電腦和手機(jī)埃撵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甥材,“玉大人盯另,你說我怎么就攤上這事≈拚裕” “怎么了鸳惯?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵商蕴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我芝发,道長(zhǎng)绪商,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任辅鲸,我火速辦了婚禮格郁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘独悴。我一直安慰自己例书,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布刻炒。 她就那樣靜靜地躺著决采,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坟奥。 梳的紋絲不亂的頭發(fā)上树瞭,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音爱谁,去河邊找鬼晒喷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛访敌,可吹牛的內(nèi)容都是我干的凉敲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捐顷,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼荡陷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起迅涮,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤废赞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后叮姑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唉地,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年传透,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耘沼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡朱盐,死狀恐怖群嗤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兵琳,我是刑警寧澤狂秘,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布骇径,位于F島的核電站,受9級(jí)特大地震影響者春,放射性物質(zhì)發(fā)生泄漏破衔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一钱烟、第九天 我趴在偏房一處隱蔽的房頂上張望晰筛。 院中可真熱鬧,春花似錦拴袭、人聲如沸读第。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)卦方。三九已至羊瘩,卻和暖如春泰佳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尘吗。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工逝她, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人睬捶。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓黔宛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親擒贸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臀晃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354