.NET5中AOP的5個(gè)Filter

??AOP(Aspect Oriented Programming)住诸,即面向切面編程骑祟。可以在不修改之前的代碼為基礎(chǔ)闽撤,動(dòng)態(tài)增加新功能。.NET5中提供了5種AOP的Filter脯颜,分別是

  • ActionFilter(方法)
  • ResourceFilter(資源)
  • ExceptionFilter(異常)
  • ResultFilter(結(jié)果)
  • AuthorizationFilter(鑒權(quán)授權(quán))
Filter執(zhí)行過程

1. ActionFilter

??ActionFilter在方法的執(zhí)行前后可執(zhí)行相應(yīng)操作哟旗。

1.1 ActionFilter基本使用

??(1) 自定義一個(gè)CustomActionFilterAttribute,并且繼承Attribute栋操,實(shí)現(xiàn)IActionFilterOnActionExecutingOnActionExecuted方法闸餐。OnActionExecuting在方法執(zhí)行前執(zhí)行,OnActionExecuted在方法執(zhí)行后執(zhí)行矾芙。

    public class CustomActionFilterAttribute : Attribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            Console.WriteLine("執(zhí)行OnActionExecuting");
        }
        public void OnActionExecuted(ActionExecutedContext context)
        {
            Console.WriteLine("執(zhí)行OnActionExecuted");
        }
    }

??(2) 在Controller的方法上添加特性標(biāo)記舍沙。

    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        [CustomActionFilter]
        public IActionResult Index()
        {
            Console.WriteLine("執(zhí)行控制器中的Index");
            return View();
        }
        // ...
    }
}

打印的結(jié)果為:

執(zhí)行OnActionExecuting
執(zhí)行控制器中的Index
執(zhí)行OnActionExecuted

1.2 ActionFilter的多種使用

??除上述來使用ActionFilter,也可通過繼承ActionFilterAttribute(系統(tǒng)提供的實(shí)現(xiàn))剔宪,根據(jù)自己的需要拂铡,覆寫不同的方法,達(dá)到自己的訴求葱绒。

    public class CustomActionFilterSystemAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            Console.WriteLine("執(zhí)行OnActionExecuting");
        }
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            Console.WriteLine("執(zhí)行OnActionExecuted");
        }
    }

??異步版本的實(shí)現(xiàn)和媳,通過實(shí)現(xiàn)IAsyncActionFilter接口來實(shí)現(xiàn)。

    public class CustomActionFilterAsyncAttribute : Attribute, IAsyncActionFilter
    {
        public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            return Task.Run(() => {
                Console.WriteLine("執(zhí)行OnActionExecutionAsync");
            });
        }
    }

1.3 ActionFilter的應(yīng)用

??可以用來記錄日志哈街,通過log4net將日志寫入文件留瞳,ILogger依賴注入。當(dāng)構(gòu)造函數(shù)有了參數(shù)后控制器方法上的[CustomActionFilter]特性就不能這么寫了骚秦,應(yīng)該寫為[TypeFilter(typeof(CustomActionFilterAttribute))].

    public class CustomActionFilterAttribute : Attribute, IActionFilter
    {
        private ILogger<CustomActionFilterAttribute> _logger = null;
        public CustomActionFilterAttribute(ILogger<CustomActionFilterAttribute> logger)
        {
            _logger = logger;
        }
        public void OnActionExecuting(ActionExecutingContext context)
        {
            _logger.LogInformation(JsonConvert.SerializeObject(context.HttpContext.Request.Query));
            _logger.LogInformation("執(zhí)行CustomActionFilterAttribute.OnActionExecuting");
        }
        public void OnActionExecuted(ActionExecutedContext context)
        {
            _logger.LogInformation(JsonConvert.SerializeObject(context.Result));
            _logger.LogInformation("執(zhí)行CustomActionFilterAttribute.OnActionExecuted");
        }
    }

1.4 ActionFilter的多種注冊(cè)

??(1)[CustomActionFilter]---Fitler必須有無參數(shù)構(gòu)造函數(shù)她倘。
??(2)[TypeFilter(typeof(CustomActionFilterAttribute))],可以沒有無參數(shù)構(gòu)造函數(shù)作箍,可以支持依賴注入硬梁。
??(3)[ServiceFilter(typeof(CustomActionFilterAttribute))],可以沒有無參數(shù)構(gòu)造函數(shù)胞得,可以支持依賴注入荧止,但是必須要注冊(cè)服務(wù)。

1.5 FilterFactory擴(kuò)展定制

??為什么寫上TypeFilter這樣的特性就可以支持依賴注入呢?它是由IOC容器來完成的跃巡。

??(1)現(xiàn)在我們自定義一個(gè)特性類CustomFilterFactory危号,繼承Attribute,實(shí)現(xiàn)接口IFilterFactory,并實(shí)現(xiàn)接口中的方法素邪。

    public class CustomFilterFactory : Attribute, IFilterFactory
    {
        private readonly Type _type = null;
        public bool IsReusable => true;
        public CustomFilterFactory(Type type)
        {
            _type = type;
        }

        public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
        {
            object oInstance = serviceProvider.GetService(_type);
            return (IFilterMetadata)oInstance;
        }
    }

??(2)在Startup類的ConfigureServices中注冊(cè)外莲。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddTransient<CustomActionFilterAttribute>();
        }

??(3)最后再將 [CustomFilterFactory(typeof(CustomActionFilterAttribute))]標(biāo)記到控制器的Action方法上就行了,和[TypeFilter(typeof(CustomActionFilterAttribute))]效果一樣兔朦。

1.6 Filter的生效范圍

  • 標(biāo)記在Action上偷线,就只對(duì)當(dāng)前Action生效。
  • 標(biāo)記在Controller上沽甥,就對(duì)Controller上中的所有Action生效声邦。
  • 全局注冊(cè),對(duì)于當(dāng)前整個(gè)項(xiàng)目中的Action都生效摆舟,在ConfigureServices中增加以下代碼即可
            services.AddMvc(option =>
            {
                option.Filters.Add<CustomActionFilterAttribute>(); //全局注冊(cè):
            });

1.7 Filter的執(zhí)行順序

??如果定義三個(gè)actionFilter亥曹,分別注冊(cè)全局,控制器盏檐、Action;執(zhí)行順序如何呢歇式?

<1> 控制器實(shí)例化
<2> 全局注冊(cè)的Filter - OnActionExecuting
<3> 控制器注冊(cè)的Filter - OnActionExecuting
<4> Actioin注冊(cè)的Filter - OnActionExecuting
<5> 執(zhí)行Action內(nèi)部的邏輯
<6> Action注冊(cè)的Filter - OnActionExecuted
<7> 控制器注冊(cè)的Filter - OnActionExecuted
<8> 全局注冊(cè)的Filter - OnActionExecuted

??如果想要改變執(zhí)行順序驶悟,需要在注冊(cè)Filter的時(shí)候胡野,指定Order的值,執(zhí)行順序會(huì)按照值從小到大執(zhí)行痕鳍。例如在方法上添加[CustomActionActionFilterAtrribute(Order = -1)]硫豆,不添加則Order值為0。

1.8 Filter匿名

??如果全局注冊(cè)笼呆,F(xiàn)ilter生效于所有的Acion熊响,如果有部分Action我希望不生效怎么辦呢?這就需要匿名诗赌,可以避開Filter的檢查汗茄。

??下面自定義Filter匿名。
??(1)自定義一個(gè)特性類CustomAllowAnonymousAttributet铭若,將[CustomAllowAnonymous]特性添加到需要避開的方法上洪碳。
??(2)在需要匿名的Filter內(nèi)部,檢查是否需要匿名(檢查是否標(biāo)記的有匿名特性),如果有就直接避開叼屠。

        public void OnActionExecuting(ActionExecutingContext context)
        {
            if(context.ActionDescriptor.EndpointMetadata.Any(item=>item.GetType() == typeof(CustomAllowAnonymousAttribute)))
            {
                return;
            }
            // ......
        }

2. ResourceFilter

??ResourceFilter就是為了緩存而存在的瞳腌。

    public class CustomResourceFilterAttribute : Attribute, IResourceFilter
    {
        private static Dictionary<string, object> CacheDictionary = new Dictionary<string, object>();
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            //在這里就判斷是否有緩存,只要是key 不變镜雨,緩存就不變
            string key = context.HttpContext.Request.Path;
            if (CacheDictionary.Any(item => item.Key == key))
            {
                //斷路器嫂侍,只要是對(duì)Result賦值,就不繼續(xù)往后走了; 
                context.Result = CacheDictionary[key] as IActionResult;
            }
            Console.WriteLine("執(zhí)行OnResourceExecuting");
        }
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            string key = context.HttpContext.Request.Path;
            CacheDictionary[key] = context.Result;
            Console.WriteLine("執(zhí)行OnResourceExecuted");
        }
    }
        [CustomResourceFilter]
        public IActionResult IndexResource()
        {
            ViewBag.Date = DateTime.Now;
            return View();
        }

3. ExceptionFilter

??ExceptionFilter用來處理異常挑宠。

??(1)自定義一個(gè)CustomExceptionFilterAttribute ,實(shí)現(xiàn)IExceptionFilter接口菲盾。
??(2)實(shí)現(xiàn)方法,先判斷痹栖,異常是否被處理過亿汞,如果沒有被處理過,就處理揪阿。如果是ajax請(qǐng)求疗我,就返回JosnResult,如果不是Ajax請(qǐng)求南捂,就返回錯(cuò)誤頁(yè)面吴裤。
??(3)全局注冊(cè)使用(和之前的ActionFilter全局注冊(cè)一樣)。

    public class CustomExceptionFilterAttribute : Attribute, IExceptionFilter
    {
        private IModelMetadataProvider _modelMetadataProvider = null;

        public CustomExceptionFilterAttribute(IModelMetadataProvider modelMetadataProvider)
        {
            _modelMetadataProvider = modelMetadataProvider;
        }
        public void OnException(ExceptionContext context)
        {
            if (!context.ExceptionHandled) //異常是否被處理過
            {
                //在這里處理  如果是Ajax請(qǐng)求===返回Json
                if (this.IsAjaxRequest(context.HttpContext.Request))//header看看是不是XMLHttpRequest
                {
                    context.Result = new JsonResult(new
                    {
                        Result = false,
                        Msg = context.Exception.Message
                    });//中斷式---請(qǐng)求到這里結(jié)束了溺健,不再繼續(xù)Action
                }
                else
                {
                    //跳轉(zhuǎn)到異常頁(yè)面
                    var result = new ViewResult { ViewName = "~/Views/Shared/Error.cshtml" };
                    result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
                    result.ViewData.Add("Exception", context.Exception);

                    context.Result = result; //斷路器---只要對(duì)Result賦值--就不繼續(xù)往后了麦牺;
                }
                context.ExceptionHandled = true;
            }
        }

        private bool IsAjaxRequest(HttpRequest request)
        {
            string header = request.Headers["X-Requested-With"];
            return "XMLHttpRequest".Equals(header);
        }
    }

?ExceptionFilter能捕捉到哪些異常?

  • 控制器實(shí)例化異常 [True]
  • 異常發(fā)生在Try-cache中 [False]
  • 在視圖中發(fā)生異常 [False]
  • Service層發(fā)生異常 [True]
  • 在Action中發(fā)生異常 [True]
  • 請(qǐng)求錯(cuò)誤路徑異常 [True] 可以使用中間件來支持鞭缭,只要不是200的狀態(tài)剖膳,就都可以處理。

4. ResultFilter

??ResultFilter在return 返回時(shí)調(diào)用岭辣。

??它的應(yīng)用吱晒,比如雙語(yǔ)言系統(tǒng),其實(shí)就需要兩個(gè)視圖根據(jù)語(yǔ)言的不同沦童,來選擇不同的視圖來渲染仑濒。因?yàn)樵阡秩疽晥D之前,會(huì)進(jìn)入到OnResultExecuting方法偷遗,就可以在這個(gè)方法中確定究竟使用哪一個(gè)視圖文件墩瞳。

??(1)自定義一個(gè)類,繼承Attribute,實(shí)現(xiàn)IResultFilter接口氏豌,實(shí)現(xiàn)方法
??(2)標(biāo)記在Action方法頭上
??(3)執(zhí)行順序:視圖執(zhí)行前喉酌,渲染視圖,視圖執(zhí)行后

    public class CustomResultFilterAttribute : Attribute, IResultFilter
    {

        private IModelMetadataProvider _modelMetadataProvider = null;

        public CustomResultFilterAttribute(IModelMetadataProvider modelMetadataProvider)
        {
            _modelMetadataProvider = modelMetadataProvider;
        }

        /// <summary>
        /// 渲染視圖之前執(zhí)行
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuting(ResultExecutingContext context)
        {
            //在這里就可以有一個(gè)判斷泵喘,符合某個(gè)情況泪电,就使用哪一個(gè)視圖; 
            Console.WriteLine("渲染視圖之前執(zhí)行");
            string view = context.HttpContext.Request.Query["View"];//也可以是配置文件
            if (view == "1")  //中文
            {
                var result = new ViewResult { ViewName = "~/Views/Seventh/IndexOne.cshtml" };
                result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
                context.Result = result;
            }
            else
            {
                var result = new ViewResult { ViewName = "~/Views/Seventh/IndexOne-2.cshtml" };
                result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
                context.Result = result;
            }

        }

        /// <summary>
        /// 渲染視圖之后執(zhí)行
        /// </summary>
        /// <param name="context"></param>
        public void OnResultExecuted(ResultExecutedContext context)
        {
            Console.WriteLine("渲染視圖之后執(zhí)行");
        }
    }

5. AuthorizationFilter

AuthorizationFilter用來做鑒權(quán)授權(quán)涣旨。通過中間件來支持歪架。

5.1 鑒權(quán)授權(quán)

??(1)在Startup中方法Configure的app.UseRouting()之后,在app.UseEndpoints()之前霹陡,增加鑒權(quán)授權(quán)和蚪。 鑒權(quán)app.UseAuthentication(),授權(quán)app.UseAuthorization()止状。

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            ......
            // 鑒權(quán) 監(jiān)測(cè)用戶是否登錄
            app.UseAuthentication();
            // 授權(quán) 監(jiān)測(cè)有沒有權(quán)限訪問后續(xù)頁(yè)面
            app.UseAuthorization();
            ......
        }

??(2)在Startup中方法ConfigureServices內(nèi)添加注冊(cè)。

        public void ConfigureServices(IServiceCollection services)
        {
            ......
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = new PathString("/Home/Login"); //如果授權(quán)失敗就跳轉(zhuǎn)到登錄
                });
            ......
        }

??(3)在指定Action上加上[Authorize]特性做鑒權(quán)授權(quán)攒霹。也可以全局標(biāo)記怯疤。

        [Authorize]
        public IActionResult Index()
        {
            return View();
        }
        [AllowAnonymous]  //避開權(quán)限檢查
        public IActionResult Login()
        {
            return View();
        }
        [HttpPost]
        [AllowAnonymous]
        public IActionResult Login(string name, string password, string verify)
        {
            string verifyCode = base.HttpContext.Session.GetString("CheckCode");
            //if (verifyCode != null && verifyCode.Equals(verify, StringComparison.CurrentCultureIgnoreCase))
            //{
                    #region 鑒權(quán):鑒權(quán),檢測(cè)有沒有登錄催束,登錄的是誰集峦,賦值給User 

                    //rolelist 是登錄成功后用戶的角色---是來自于數(shù)據(jù)庫(kù)的查詢;不同的用戶會(huì)查詢出不同的角色抠刺;
                    var rolelist = new List<string>() {

                            "Admin",
                            "Teacher",
                            "Student"
                    };
                    //ClaimTypes.Role就是做權(quán)限認(rèn)證的標(biāo)識(shí)塔淤;
                    var claims = new List<Claim>()//鑒別你是誰,相關(guān)信息
                    {
                        new Claim(ClaimTypes.Role,"Admin"),
                        new Claim(ClaimTypes.Name,name),
                        new Claim("password",password),//可以寫入任意數(shù)據(jù)
                        new Claim("Account","admin"),
                        new Claim("role","admin"),
                        new Claim("admin","admin"),
                        new Claim("User","admin")
                    };
                    foreach (var role in rolelist)
                    {
                        claims.Add(new Claim(ClaimTypes.Role, role));
                    }
                    ClaimsPrincipal userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
                    HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
                    {
                        ExpiresUtc = DateTime.UtcNow.AddMinutes(30),//過期時(shí)間:30分鐘

                    }).Wait();
                    #endregion

                    var user = HttpContext.User;
                    return base.Redirect("/Home/Index");
                }
                else
                {
                    base.ViewBag.Msg = "賬號(hào)密碼錯(cuò)誤";
                }
                #endregion

            //}
            //else
            //{
            //    base.ViewBag.Msg = "驗(yàn)證碼錯(cuò)誤";
            //}
            return View();
        }

5.1 鑒權(quán)授權(quán)-角色授權(quán)

??即用戶角色不同速妖,在訪問頁(yè)面時(shí)需要做不同的攔截高蜂。

??(1)一個(gè)特性標(biāo)記到方法上,通過逗號(hào)分隔不同角色罕容,只要是有一個(gè)角色符合就能夠訪問备恤,角色之間是或者的關(guān)系。

        [Authorize(Roles = "Admin,Teacher,Student")]

??(2)多個(gè)特性標(biāo)記锦秒,多個(gè)角色之前是且的關(guān)系露泊,必須要包含所有的角色,才能夠訪問旅择。

        [Authorize(Roles = "Admin")]
        [Authorize(Roles = "Teacher")]
        [Authorize(Roles = "Student")] 

5.2 鑒權(quán)授權(quán)-策略授權(quán)

??上面的角色授權(quán)是在代碼中寫死了角色惭笑,但我們更希望能夠用處理邏輯來完成校驗(yàn),就需要策略授權(quán)砌左。

??(1)添加CustomAuthorizationRequirement類繼承自IAuthorizationRequirement脖咐,用來傳遞策略名稱铺敌。

    public class CustomAuthorizationRequirement : IAuthorizationRequirement
    {
        public string Name { get; set; }
        public CustomAuthorizationRequirement(string policyname)
        {
            this.Name = policyname;
        }
    }

??(2)添加CustomAuthorizationHandler類專用做檢驗(yàn)邏輯汇歹, 繼承自泛型抽象類AuthorizationHandler<CustomAuthorizationRequirement>

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, 
            CustomAuthorizationRequirement requirement)
        {
            if (requirement.Name == "Policy01")
            {
                ///策略1的邏輯
            }

            if (requirement.Name == "Policy02")
            {
                ///策略1的邏輯
            }

            //其實(shí)這里可以去數(shù)據(jù)庫(kù)里面去做一些查詢偿凭,然后根據(jù)用戶的信息产弹,做計(jì)算;如果符合就context.Succeed(requirement); 
            //否則就Task.CompletedTask; 

            //context.User 鑒權(quán)成功(登錄成功以后)弯囊,用戶的信息痰哨; 
            var role = context.User.FindFirst(c => c.Value.Contains("admin"));
            if (role != null)
            {
                context.Succeed(requirement); //驗(yàn)證通過了
            }
            return Task.CompletedTask; //驗(yàn)證不通過
        }

??(3)添加注冊(cè),并支持多種策略。

            services.AddSingleton<IAuthorizationHandler, CustomAuthorizationHandler>();
            services.AddAuthorization(option =>
            {
                option.AddPolicy("customPolicy01", policy =>
                {
                    policy.AddRequirements(new CustomAuthorizationRequirement("Policy01"));
                });
            });
            services.AddAuthorization(option =>
            {
                option.AddPolicy("customPolicy02", policy =>
                {
                    policy.AddRequirements(new CustomAuthorizationRequirement("Policy02"));
                });
            });

??(4)標(biāo)記到使用的方法上匾嘱。

        [Authorize(policy: "customPolicy01")]
        public IActionResult IndexPolicy()
        {
            return View();
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斤斧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子霎烙,更是在濱河造成了極大的恐慌撬讽,老刑警劉巖蕊连,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異游昼,居然都是意外死亡甘苍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門烘豌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來载庭,“玉大人,你說我怎么就攤上這事廊佩∏艟郏” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵标锄,是天一觀的道長(zhǎng)靡挥。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么能耻? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任辈末,我火速辦了婚禮,結(jié)果婚禮上毒返,老公的妹妹穿的比我還像新娘。我一直安慰自己舷手,他們只是感情好拧簸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著男窟,像睡著了一般盆赤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歉眷,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天牺六,我揣著相機(jī)與錄音,去河邊找鬼汗捡。 笑死淑际,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的扇住。 我是一名探鬼主播春缕,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼艘蹋!你這毒婦竟也來了锄贼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤女阀,失蹤者是張志新(化名)和其女友劉穎宅荤,沒想到半個(gè)月后米间,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膘侮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年屈糊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琼了。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逻锐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雕薪,到底是詐尸還是另有隱情昧诱,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布所袁,位于F島的核電站盏档,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏燥爷。R本人自食惡果不足惜蜈亩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望前翎。 院中可真熱鬧稚配,春花似錦、人聲如沸港华。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)立宜。三九已至冒萄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橙数,已是汗流浹背尊流。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留商模,地道東北人奠旺。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓蜘澜,卻偏偏與公主長(zhǎng)得像施流,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鄙信,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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