從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十四║ Vuex + JWT 實(shí)現(xiàn)授權(quán)驗(yàn)證登陸

壹周回顧

哈嘍属瓣,又是元?dú)鉂M滿的一個(gè)周一,又與大家見面了讯柔,周末就是團(tuán)圓節(jié)了抡蛙,正好咱們的前后端也要團(tuán)圓了,為什么這么說呢魂迄,因?yàn)橐院蟮拈_發(fā)可能就需要前后端一起了粗截,兩邊也終于會師了,還有幾天Vue系列就基本告一段落了极祸,大家也好好加油鴨慈格,今天將的內(nèi)容呢,其實(shí)細(xì)心的你看到題目應(yīng)該就能大家猜到了遥金,前提是一直看本系列的小伙伴們浴捆,包括之前.net core部分,這里先簡單說下上周咱們都說了什么:

周一:《十九║Vue基礎(chǔ): 樣式動態(tài)綁定+生命周期》重點(diǎn)說了下 Vue 開發(fā)中的八個(gè)生命周期稿械,這個(gè)是一個(gè)重點(diǎn)选泻,希望大家可以多看看,這個(gè)在以后的開發(fā)中會經(jīng)常遇到美莫;

周二:《二十║Vue基礎(chǔ)終篇:組件詳解+項(xiàng)目說明》重點(diǎn)說了下組件的使用页眯,包括定義、傳值厢呵、使用等等窝撵,這個(gè)更是重中之重,組件的使用在 Vue 的開發(fā)中必不可少襟铭;

周三:《二十一║Vue實(shí)戰(zhàn):開發(fā)環(huán)境搭建【詳細(xì)版】》詳細(xì)的說了下開發(fā)環(huán)境的搭建碌奉,不僅講了如何搭建短曾,還詳細(xì)的說明了每一個(gè)工具、插件的使用意義赐劣;

周四:《二十二║Vue實(shí)戰(zhàn):個(gè)人博客第一版(axios+router)》根據(jù)周三搭建的環(huán)境嫉拐,第一次創(chuàng)建了咱們第一版的個(gè)人博客,封裝了 axios 魁兼,第一次連接上了咱們之前的 .net core api婉徘;

周五:《二十三║Vue實(shí)戰(zhàn):Vuex 其實(shí)很簡單》通過一個(gè)小 DEMO 說明了 Vuex 是如何對我們的 Vue 實(shí)行狀態(tài)化管理的,讓大家對其使用有了一定的了解咐汞,為在以后的大項(xiàng)目中使用打下基礎(chǔ)盖呼;

周五的時(shí)候,咱們通過對表單的組件化碉考,來說明了 vuex 的存在意義塌计,今天咱們還是會用到這個(gè) vuex 挺身,而且還會配合著 .net core api侯谁,到底是什么呢?請看今天的講解章钾。

注意:周四的時(shí)候墙贱,只寫了個(gè)人博客的首頁,周末的時(shí)候贱傀,已經(jīng)把詳情頁更新了惨撇,大家可以自行去 Git 查看,文末有地址

image

零府寒、今天要完成右下角粉色區(qū)塊的部分

image

一魁衙、如何實(shí)現(xiàn)權(quán)限驗(yàn)證的過程

大家一定還記得之前在 .net core api 系列文章中《框架之五 || Swagger的使用 3.3 JWT權(quán)限驗(yàn)證【修改】》,咱們通過對 JWT 的講解株搔,實(shí)現(xiàn)了對接口的驗(yàn)證剖淀,大家可以去了解一下,當(dāng)時(shí)因?yàn)槭菦]有前端纤房,所以咱們就直接用的 Swagger 接口文檔來手動設(shè)置的權(quán)限驗(yàn)證纵隔,當(dāng)時(shí)群里有很多小伙伴對這個(gè)不是很明白,我也是簡單說了下炮姨,通過手動在 swagger 中輸入Header 捌刮,變成每次 vue 的 axios 請求的 Header 中添加 Token,這個(gè) Token 就是咱們手動配置的那個(gè)舒岸,因?yàn)楫?dāng)時(shí)沒有前后端搭配绅作,所以只是比較籠統(tǒng)的說了下這個(gè)流程,今天呢蛾派,就重點(diǎn)來說下這個(gè)授權(quán)登陸驗(yàn)證俄认,也為下邊的管理后臺鋪路堕扶,這里配合 Vue 前端,再仔細(xì)講講是如何實(shí)現(xiàn)前后端同時(shí)驗(yàn)證的:

image

上圖中說的也是很詳細(xì)了梭依,主要分為兩個(gè)驗(yàn)證:

1稍算、前端驗(yàn)證(藍(lán)色部分),用戶訪問一個(gè)頁面役拴,首先判斷是否需要驗(yàn)證登陸糊探,比如管理后臺,或者訂單系統(tǒng)的下單頁(首頁和詳情頁自然是不需要用戶登陸的河闰,購物車和訂單等必須登陸科平,當(dāng)然有些游客也可以購買的除外),然后去驗(yàn)證是否存在 Token姜性,存在就添加到 axios 的 Header 中去請求后端 API瞪慧,反之則去登陸頁登陸;

2部念、后端驗(yàn)證(綠色部分)弃酌,這個(gè)就是咱們之前在說 .net core api 的時(shí)候說到的 JWT 授權(quán)驗(yàn)證,根據(jù)當(dāng)前前端 axios 請求中傳來的 Token 儡炼,解析出是否被篡改妓湘,以及是否會相應(yīng)的權(quán)限,這樣就可以進(jìn)一步返回?cái)?shù)據(jù)了乌询;

這個(gè)時(shí)候大家一定會有疑惑了榜贴,既然現(xiàn)在每一個(gè)接口都定義了權(quán)限,為什么要倆邊都需要驗(yàn)證妹田,只需要后端 api 一個(gè)驗(yàn)證不就行了唬党,何必這么麻煩?我認(rèn)為是這樣的:

首先前端驗(yàn)證的主要目的是:通過手動配置鬼佣,可以讓用戶去主動獲取 Token 驶拱,不用每次都去獲取,而且也減輕了后端請求的次數(shù)沮趣,總不能是先去發(fā)送請求屯烦,再判斷當(dāng)前頁面是否需要登陸吧,嗯房铭,總結(jié)來說驻龟,

前端是為了頁面級登陸,后端是為了接口級驗(yàn)證缸匪,而且也是想把 vue 前端工程化的思想翁狐。

二、結(jié)合API設(shè)計(jì)登錄頁 —— 實(shí)現(xiàn)后端驗(yàn)證

1凌蔬、引入 ElementUI 樣式框架

因?yàn)橹笮枰粋€(gè)管理后臺露懒,所以考慮著增加一個(gè)框架闯冷,目前比較流行的就是 ElementUI 和 IView,今天咱們先說一下引用 ElementUI

首先懈词,在項(xiàng)目中 執(zhí)行 npm install蛇耀,初始化以后,在 node_modules 中查看是否存在 element-ui 文件夾坎弯,如果沒有纺涤,則執(zhí)行

 npm i element-ui -S

然后就可以看到項(xiàng)目中已經(jīng)成功安裝 elementui 了

image

然后、在項(xiàng)目的入口配置文件 main.js 中抠忘,引用

import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI)

如果項(xiàng)目沒有報(bào)錯(cuò)撩炊,到此則安裝成功。

2崎脉、添加統(tǒng)一登陸頁面

第一拧咳、在 src 的 views 文件夾內(nèi),添加 Login.vue 頁面囚灼,并添加內(nèi)容:

<template>
    <el-row type="flex" justify="center">
        <el-form ref="loginForm" :model="user" :rules="rules" status-icon label-width="50px">
            <el-form-item label="賬號" prop="name">
                <el-input v-model="user.name"></el-input>
            </el-form-item>
            <el-form-item label="密碼" prop="pass">
                <el-input v-model="user.pass" type="password"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" icon="el-icon-upload" @click="login">登錄</el-button>
            </el-form-item>
        </el-form>
    </el-row>
</template>

<script> export default {
  methods: {
    login() {//使用elementui validate驗(yàn)證
      this.$refs.loginForm.validate(valid => { if (valid) {這里在下邊會改寫成登陸信息 if (this.user.name === "admin" && this.user.pass === "123") { this.$notify({
              type: "success",
              message: "歡迎你," + this.user.name + "!",
              duration: 3000 }); this.$router.replace("/");
          } else { this.$message({
              type: "error",
              message: "用戶名或密碼錯(cuò)誤",
              showClose: true });
          }
        } else { return false;
        }
      });
    }
  },
  data() { return {
      user: {},//配合頁面內(nèi)的 prop 定義數(shù)據(jù)
      rules: {//配合頁面內(nèi)的 prop 定義規(guī)則
        name: [{ required: true, message: "用戶名不能為空", trigger: "blur" }],
        pass: [{ required: true, message: "密碼不能為空", trigger: "blur" }]
      }
    };
  }
}; </script>

添加路由后骆膝,測試頁面是否可行

image

3、配合后臺登陸請求

完善 BlogController.cs 頁面啦撮,稍微調(diào)整了下接口谭网,和之前的沒有差別,并增加權(quán)限驗(yàn)證

image
 /// <summary>
        /// 獲取博客列表 /// </summary>
        /// <param name="id"></param>
        /// <param name="page"></param>
        /// <param name="bcategory"></param>
        /// <returns></returns>
 [HttpGet] public async Task<object> Get(int id, int page = 1, string bcategory = "技術(shù)博文")
        { int intTotalCount = 6; int TotalCount = 1;
            List<BlogArticle> blogArticleList = new List<BlogArticle>(); if (redisCacheManager.Get<object>("Redis.Blog") != null)
            {
                blogArticleList = redisCacheManager.Get<List<BlogArticle>>("Redis.Blog");
            } else {
                blogArticleList = await blogArticleServices.Query(a => a.bcategory == bcategory);
                redisCacheManager.Set("Redis.Blog", blogArticleList, TimeSpan.FromHours(2));
            }

            TotalCount = blogArticleList.Count() / intTotalCount;

            blogArticleList = blogArticleList.OrderByDescending(d => d.bID).Skip((page - 1) * intTotalCount).Take(intTotalCount).ToList(); foreach (var item in blogArticleList)
            { if (!string.IsNullOrEmpty(item.bcontent))
                {
                    int totalLength = 500; if (item.bcontent.Length > totalLength)
                    {
                        item.bcontent = item.bcontent.Substring(0, totalLength);
                    }
                }
            } var data = new { success = true, page = page, pageCount = TotalCount, data = blogArticleList }; return data;
        } // GET: api/Blog/5
        /// <summary>
        /// 獲取詳情 /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")] public async Task<object> Get(int id)
        { var model = await blogArticleServices.getBlogDetails(id); var data = new { success = true, data = model }; return data;
        }

調(diào)整 LoginController.cs 的獲取 Token 方法:

  /// <summary>
        /// 獲取JWT的方法 /// </summary>
        /// <param name="id">id</param>
        /// <param name="sub">角色</param>
        /// <returns></returns>
 [HttpGet]
        [Route("Token")] public JsonResult GetJWTStr(string name, string pass)
        { string jwtStr = string.Empty; bool suc = false; //這里就是用戶登陸以后赃春,通過數(shù)據(jù)庫去調(diào)取數(shù)據(jù),分配權(quán)限的操作 //這里直接寫死了
            if (name == "admins" && pass == "admins")
            {
                TokenModelJWT tokenModel = new TokenModelJWT();
                tokenModel.Uid = 1;
                tokenModel.Role = "Admin";

                jwtStr = JwtHelper.IssueJWT(tokenModel);
                suc = true;
            } else {
                jwtStr = "login fail!!!";
            } var result = new {
                data = new { success = suc, token = jwtStr }
            }; return Json(result);
        }

4劫乱、修改 前端的 Login.vue 頁面的登陸方法织中,獲取到 Token ,并把其保存到 Vuex 中

注意:目前是用的 localStorage 本地存儲的方法衷戈,Vuex 暫時(shí)沒有完成狭吼,因?yàn)樵诼酚?router 中,取不到殖妇,有知道的小伙伴請留言

<script> export default {
  methods: {
    login: function() {
      let that = this; this.$refs.loginForm.validate(valid => { if (valid) { this.$api.get( "Login/Token",
            { name: that.user.name, pass: that.user.pass },
            r => { if (r.data.success) { var token = r.data.token;
                that.$store.commit("saveToken", token);//保存到 Vuex刁笙,還沒有實(shí)現(xiàn)
                window.localStorage.setItem("Token",token);//保存到本地
                this.$notify({
                  type: "success",
                  message: "歡迎你," + this.user.name + "!",
                  duration: 3000 });
                console.log(that.$store.state.token); this.$router.replace("/");
              } else { this.$message({
                  type: "error",
                  message: "用戶名或密碼錯(cuò)誤",
                  showClose: true });
              }
            }
          );
        } else { return false;
        }
      });
    }
  },
  data() { return {
      user: {},
      rules: {
        name: [{ required: true, message: "用戶名不能為空", trigger: "blur" }],
        pass: [{ required: true, message: "密碼不能為空", trigger: "blur" }]
      }
    };
  }
}; </script>

5、修改 vuex 倉庫谦趣,把 token 存進(jìn)store中

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex); const store = new Vuex.Store({ // 初始化的數(shù)據(jù)
 state: {
    formDatas: null,
    token: ""http://定義全局變量 token
 }, // 改變state里面的值得方法
 mutations: {
    getFormData(state, data) {
      state.formDatas = data;
    },
    saveToken(state, data) {//將 token 保存
      state.token = data;
    }
  }
}); // 輸出模塊
export default store;

6疲吸、這個(gè)時(shí)候要修改下之前我們封裝的 http.js 方法限佩,因?yàn)楫?dāng)時(shí)我們過濾掉了失敗的方法赃承,這里要打開下,大家自行修改下

image

這個(gè)時(shí)候碾篡,我們再登陸的話舰绘,已經(jīng)發(fā)生變化

image

這個(gè)時(shí)候大家可以看到蹂喻,我們成功的登陸了(右上角有歡迎提示)葱椭,然后 token 也成功的保存到 stroe/localStorage 里(下邊控制臺輸出),

因?yàn)槲覀冊诓┛晚撛黾恿藱?quán)限口四,雖然我們是用的 admin 賬號孵运,但是 Header 中還沒有添加Token,所以現(xiàn)在還是 401蔓彩,那如何才能有效的增加請求 Header 呢掐松,請往下看,權(quán)限驗(yàn)證前端部分粪小。

三大磺、實(shí)現(xiàn)一:登陸攔截驗(yàn)證——路由攔截

1、修改 router.js 路由探膊,實(shí)現(xiàn)按需登陸

在需要登陸的地方杠愧,增加登陸要求字段,

然后增加 beforeEach 鉤子函數(shù)(這里有一個(gè)問題逞壁,只能獲取到本地緩存數(shù)據(jù)流济,無法獲取 Vuex ,正在研究中)

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import FormVuex from "./views/FormVuex.vue";
import Content from "./views/content";
import Login from "./views/Login";
import store from "./store";

Vue.use(Router); const router = new Router({
  mode: "history", base: process.env.BASE_URL,
  routes: [
    {
      path: "/",
      name: "home",
      component: Home,
      meta: {
        requireAuth: true // 添加該字段腌闯,表示進(jìn)入這個(gè)路由是需要登錄的
 }
    },
    {
      path: "/Vuex",
      name: "Vuex",
      component: FormVuex
    },
    {
      path: "/Content/:id",
      name: "Content",
      component: Content
    },
    {
      path: "/Login",
      name: "Login",
      component: Login
    },
    {
      path: "/about",
      name: "about", // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ "./views/Form.vue")
    }
  ]
});

router.beforeEach((to, from, next) => { if (to.meta.requireAuth) {  // 判斷該路由是否需要登錄權(quán)限
        if (window.localStorage.Token&&window.localStorage.Token.length>=128) {  // 通過vuex state獲取當(dāng)前的token是否存在
 next();
        } else {
            next({
                path: '/login',
                query: {redirect: to.fullPath} // 將跳轉(zhuǎn)的路由path作為參數(shù)绳瘟,登錄成功后跳轉(zhuǎn)到該路由
 })
        }
    } else {
        next();
    }
})

export default router;

2、修改 http.js 封裝方法姿骏,自動在請求中把 Token 添加到 Header 中

上邊的路由設(shè)置糖声,僅僅是對 Token 進(jìn)行判斷,還沒有添加到 Header 里分瘦,更沒有進(jìn)行驗(yàn)證

import store from "../store";
import router from "../router.js"; // 配置API接口地址
var root = "http://localhost:58427/api"; var root1 = "http://123.206.33.109:8018/api"; // 引用axios
var axios = require("axios"); // 自定義判斷元素類型JS
function toType(obj) { return {}.toString
    .call(obj)
    .match(/\s([a-zA-Z]+)/)[1]
    .toLowerCase();
} // 參數(shù)過濾函數(shù)
function filterNull(o) { for (var key in o) { if (o[key] === null) {
      delete o[key];
    } if (toType(o[key]) === "string") {
      o[key] = o[key].trim();
    } else if (toType(o[key]) === "object") {
      o[key] = filterNull(o[key]);
    } else if (toType(o[key]) === "array") {
      o[key] = filterNull(o[key]);
    }
  } return o;
} // http request 攔截器
axios.interceptors.request.use(
  config => { if (window.localStorage.Token&&window.localStorage.Token.length>=128) {//store.state.token 獲取不到值蘸泻?? // 判斷是否存在token嘲玫,如果存在的話悦施,則每個(gè)http header都加上token
      config.headers.Authorization = window.localStorage.Token;
    } return config;
  },
  err => { return Promise.reject(err);
  }
); // http response 攔截器
axios.interceptors.response.use(
  response => { return response;
  },
  error => { if (error.response) { switch (error.response.status) { case 401: // 返回 401 清除token信息并跳轉(zhuǎn)到登錄頁面
 router.replace({
            path: "login",
            query: { redirect: router.currentRoute.fullPath }
          });
      }
    } return Promise.reject(error.response.data); // 返回接口返回的錯(cuò)誤信息
 }
); /* 接口處理函數(shù)
  這個(gè)函數(shù)每個(gè)項(xiàng)目都是不一樣的,我現(xiàn)在調(diào)整的是適用于 https://cnodejs.org/api/v1 的接口去团,如果是其他接口
  需要根據(jù)接口的參數(shù)進(jìn)行調(diào)整抡诞。參考說明文檔地址: https://cnodejs.org/topic/5378720ed6e2d16149fa16bd 主要是,不同的接口的成功標(biāo)識和失敗提示是不一致的土陪。
  另外昼汗,不同的項(xiàng)目的處理方法也是不一致的,這里出錯(cuò)就是簡單的alert */ function apiAxios(method, url, params, success, failure) { if (params) { params = filterNull(params);
  }
  axios({
    method: method,
    url: url,
    data: method === "POST" || method === "PUT" ? params : null, params: method === "GET" || method === "DELETE" ? params : null,
    baseURL: root,
    withCredentials: false })
    .then(function(res) {
      success(res.data);
    })
    .catch(function(err) {
      let res = err.response; if (err) {
        window.alert("api error, HTTP CODE: " + res.status);
      }
    });
} // 返回在vue模板中的調(diào)用接口
export default { get: function(url, params, success, failure) { return apiAxios("GET", url, params, success, failure);
  },
  post: function(url, params, success, failure) { return apiAxios("POST", url, params, success, failure);
  },
  put: function(url, params, success, failure) { return apiAxios("PUT", url, params, success, failure);
  },
  delete: function(url, params, success, failure) { return apiAxios("DELETE", url, params, success, failure);
  }
};

運(yùn)行項(xiàng)目查看:

image

大家觀察可以看到旺坠,我們第一次點(diǎn)擊 Home 的時(shí)候乔遮,發(fā)現(xiàn)跳轉(zhuǎn)到了 Login 頁面,然后登陸后取刃,自動跳轉(zhuǎn)首頁蹋肮,并成功獲取到數(shù)據(jù)出刷,登陸成功!

四坯辩、說明

今天因?yàn)闀r(shí)間的關(guān)系馁龟,沒有把 Vuex 在路由中如何獲取研究出來,這里先用了本地緩存來代替了漆魔,大家如果有知道的小伙伴坷檩,請留言哈~~~不勝感激,

五改抡、CODE

前端:
https://github.com/anjoy8/Blog.Vue

后端:

https://github.com/anjoy8/Blog.Core

QQ群:
867095512 (blod.core)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矢炼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子阿纤,更是在濱河造成了極大的恐慌句灌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件欠拾,死亡現(xiàn)場離奇詭異胰锌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)藐窄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門资昧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荆忍,你說我怎么就攤上這事格带。” “怎么了东揣?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵践惑,是天一觀的道長。 經(jīng)常有香客問我嘶卧,道長,這世上最難降的妖魔是什么凉袱? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任芥吟,我火速辦了婚禮,結(jié)果婚禮上专甩,老公的妹妹穿的比我還像新娘钟鸵。我一直安慰自己,他們只是感情好涤躲,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布棺耍。 她就那樣靜靜地躺著,像睡著了一般种樱。 火紅的嫁衣襯著肌膚如雪蒙袍。 梳的紋絲不亂的頭發(fā)上俊卤,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音害幅,去河邊找鬼消恍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛以现,可吹牛的內(nèi)容都是我干的狠怨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼邑遏,長吁一口氣:“原來是場噩夢啊……” “哼佣赖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起记盒,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤憎蛤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后孽鸡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹂午,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年彬碱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豆胸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡巷疼,死狀恐怖晚胡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嚼沿,我是刑警寧澤估盘,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站骡尽,受9級特大地震影響遣妥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攀细,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一箫踩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谭贪,春花似錦境钟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春缚态,著一層夾襖步出監(jiān)牢的瞬間磁椒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工猿规, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衷快,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓姨俩,卻偏偏與公主長得像蘸拔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子环葵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

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