從壹開始前后端分離 [ vue + .netcore 補(bǔ)程 ] 三十一║ Nuxt終篇:基于Vuex的權(quán)限驗(yàn)證探究

緣起

哈嘍大家好,今天周四啦瞻佛,樓主明天要正式放假了,這里先祝大家節(jié)日快樂咯娇钱,希望在家里能繼續(xù)研究點(diǎn)兒東西吧伤柄,今天呢是 nuxt 的最后一篇,主要是對(duì)權(quán)限登陸進(jìn)行研究文搂,這一塊咱們之前在說第一個(gè)項(xiàng)目的時(shí)候已經(jīng)稍微說到了适刀,具體的邏輯大家可以查看這篇文章《二十四║ Vuex + JWT 實(shí)現(xiàn)授權(quán)驗(yàn)證登陸》,具體的運(yùn)行原理和流程细疚,以及什么是 vuex 蔗彤,在那里已經(jīng)說的很清楚了,今天咱們就是主要在 nuxt 框架中使用疯兼,主要的代碼的形式然遏,理論知識(shí)比較少了,大家可以歇一歇了吧彪。這幾天寫了這么多待侵,好多人可能都沒看,不過沒關(guān)系姨裸,繼續(xù)回顧:

二七║ Nuxt 基礎(chǔ):框架初探》:通過 SSR 來引入 nuxt 框架秧倾,第一次接觸到該框架;

二八║ Nuxt 基礎(chǔ):面向源碼研究Nuxt.js》:通過研究 node_modules 中的源碼傀缩,帶領(lǐng)大家一步步了解 nuxt 是如何進(jìn)行服務(wù)端渲染的那先;

二九║ Nuxt實(shí)戰(zhàn):異步實(shí)現(xiàn)數(shù)據(jù)雙端渲染》:通過首頁的數(shù)據(jù)加載,更加深刻的了解到 nuxt 的雙端渲染赡艰,異步很重要售淡;

三十║ Nuxt實(shí)戰(zhàn):動(dòng)態(tài)路由+同構(gòu)》:通過首頁和詳情頁的交互,進(jìn)一步鞏固 nuxt 的渲染模式和動(dòng)態(tài)路由效果慷垮。

從上邊大家可以看到揖闸,幾乎每一篇都會(huì)說到 nuxt 這個(gè)框架的渲染模式,這個(gè)很重要料身,更是對(duì) vue 的鞏固汤纸。好啦,馬上開始今天的講解~

零芹血、今天要完成橙色的部分

image

為詳情頁增加權(quán)限驗(yàn)證

今天呢贮泞,咱們換一種玩兒法楞慈,就是將我們的詳情頁給增加一個(gè)權(quán)限,首頁的數(shù)據(jù)大家都可以隨便看隙畜,但是詳情頁卻不能隨便看抖部,必須要登陸,那我們就需要在我們的詳情頁增加一個(gè)權(quán)限议惰,

如果 token 存在,則發(fā)送請(qǐng)求驗(yàn)證乡恕,如果不存在言询,直接跳轉(zhuǎn)到登錄頁,那我們首先要添加一個(gè)登錄頁

添加登錄頁傲宜,獲取token

在 pages頁面文件夾下运杭,新建login 文件夾,然后添加 index.vue 登陸頁面函卒,

這一塊邏輯和我們之前的很像辆憔,大家可以參考著做對(duì)比

image
<template>
  <el-row type="flex" justify="center">
    <el-card v-if="isLogin"> 歡迎:admins <br>
      <br>
      <el-button type="primary" icon="el-icon-upload" @click="loginOut">退出登錄</el-button>
    </el-card>
    <el-form v-else ref="loginForm" :model="user" :rules="rules" status-icon label-width="50px">
      <el-form-item label="賬號(hào)" 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> import Vue from "vue";
  export default {
      methods: {
        login: function() {
          let that = this;
          that.$store.commit("saveToken", ""); this.$refs.loginForm.validate(valid => { if (valid) { //發(fā)送請(qǐng)求登陸,這里要注意下返回?cái)?shù)據(jù)格式报嵌,如果有問題虱咧,參考 http.js 中的 response 設(shè)置
              Vue.http.get("Login/GetTokenNuxt?name="+that.user.name+"&pass="+that.user.name+"").then(res => { if (res.success) {
                    console.log("登陸成功"); var token = res.token;
                    that.$store.commit("saveToken", token); this.$notify({
                      type: "success",
                      message: "歡迎你," + this.user.name + "!",
                      duration: 3000 }); this.$router.replace("/");
                }
              }).catch(err => {
                console.log("點(diǎn)贊失敗", err);
              });
            } else { return false;
            }
          });
        },
        loginOut(){ this.isLogin=false; this.$store.commit("saveToken", "");
        }
      },
      data() { return {
          isLogin:false,
          user: {},
          rules: {
            name: [{ required: true, message: "用戶名不能為空", trigger: "blur" }],
            pass: [{ required: true, message: "密碼不能為空", trigger: "blur" }]
          }
        };
      },
      created() {
      }
    } </script>

自定義 elementUI 插件

image

提醒:這里我用到了 elementUI ,請(qǐng)安裝

npm i element-ui -S

安裝成功后锚国,作為插件使用腕巡,如果你不是很了解,請(qǐng)?jiān)L問官網(wǎng)《插 件》一章節(jié)血筑,這里說的很清楚绘沉,我在之前的文件中也有提到。

在 plugins/server_site 文件夾下豺总,新增 ElementUI.js 文件车伞,作為我們的插件

import Vue from 'vue' import ElementUI from 'element-ui' Vue.use(ElementUI)

然后把這個(gè) js 插件導(dǎo)入到 index.js 中,和 http.js一起注入到nuxt.config.js 中

//這個(gè)是 server_site 服務(wù)端插件全部
import Vue from "vue";
import http from "./http.js";
import "./ElementUI.js";//導(dǎo)入 elementUI插件

const install = function (VueClass, opts = {}) { // http method
    VueClass.http = http;
    VueClass.prototype.$http = http;
};
Vue.use(install);

因?yàn)槲覀兪前逊?wù)端的插件都打包了 server_site 下的index中喻喳,所以我們以后不用每一個(gè)都注入到我們的配置文件 nuxt.config.js 中另玖,只需要將 服務(wù)端插件 一個(gè)放進(jìn)去即可,但是樣式還是需要引用的

image

在 strore 文件夾中沸枯,添加 index.js 文件日矫,設(shè)置我們的store數(shù)據(jù)

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

Vue.use(Vuex); const store = () => new Vuex.Store({
    state: {
      isLogined: false,
      token: "",//這里主要是用到了 token
 userInfo: {
            name: "" },
        loginBoxVisible: false },
    mutations: { //保存 token 到 store和本地中
 saveToken(state, data) {
        state.token = data;
        window.localStorage.setItem("Token", data);
      },
        changeLoginState (state, isLogined) {
            state.isLogined = isLogined;
        },
        changeLoginBoxVisible (state, visible) {
            state.loginBoxVisible = visible;
        },
        updateUserInfo (state, userInfo) {
            state.userInfo = userInfo;
        }
    },
    actions: {
        initUser ({ state, commit }) { const user = JSON.parse(localStorage.getItem("userInfo")); if (user) {
                state.userInfo = user;
                commit("changeLoginState", true);
            }
        }
    }
});

export default store;

在詳情頁中增加權(quán)限驗(yàn)證

大家一定還記得這個(gè)圖片,這個(gè)是我們之前講到的 nuxt 的執(zhí)行流程圖绑榴,這里說下 fetch()

image

fetch 方法用于在渲染頁面前填充應(yīng)用的狀態(tài)樹(store)數(shù)據(jù)哪轿, 與 asyncData 方法類似,不同的是它不會(huì)設(shè)置組件的數(shù)據(jù)翔怎。

如果頁面組件設(shè)置了 fetch 方法窃诉,它會(huì)在組件每次加載前被調(diào)用(在服務(wù)端或切換至目標(biāo)路由之前)杨耙。

我們可以利用該方法,獲取 狀態(tài)樹 中的 token 信息飘痛,并做處理珊膜,在昨天的基礎(chǔ)上,我們只對(duì) fetch() 方法宣脉,簡單修改

<script> import Vue from "vue";
  export default {
    layout: "blog", async asyncData ({ params, error }) { // 獲取文章詳情
      let data = {}; try {
        data = await Vue.http.get(`blog/${params.id}`); return {
          data: data
        };
      } catch (e) { //error({ statusCode: 404, message: "出錯(cuò)啦" });
 }
    }, //在這里進(jìn)行判斷 token
 fetch ({ store, redirect  }) { if (!(store.state.token&&store.state.token.length>=128)) { //跳轉(zhuǎn)登錄頁
        return redirect('/login')
      }

    },
    data () { return {
        comments: []
      };
    },
    head () { return {
        title: `${this.data.btitle}`,
        meta: [
          {
            name: "description",
            content: this.data.btitle
          }
        ]
      };
    }
  }; </script>

最后在 http.js 中车柠,開啟 http 攔截器

// http.interceptors.request.use((data, headers) => { // return data; // }); //http request 攔截器
 http.interceptors.request.use(
    config => { //注意,首次服務(wù)端渲染的時(shí)候塑猖,還沒有出現(xiàn) DOM竹祷,所以找不到 windows 對(duì)象,這里用 try 處理掉了
      try { if (window.localStorage.Token&&window.localStorage.Token.length>=128) {//store.state.token 獲取不到值
          config.headers.Authorization = window.localStorage.Token;
        }
      }catch (e) {
      } return config;
    },
    err => { return Promise.reject(err);
    }
  );

查看頁面羊苟,體驗(yàn)效果

這里我們就已經(jīng)限制了詳情頁塑陵,需要登陸才能查看,其實(shí)這一塊邏輯我們可以單拿出來放到中間件 middleware 里來使用蜡励,效果會(huì)更好令花,這里舉個(gè)栗子:路由鑒權(quán)

提醒: 因?yàn)槲覀冇玫氖?store 判斷的是否登陸,但是如果刷新頁面凉倚,我們用的是 服務(wù)端渲染兼都,所以 store 會(huì)被更新掉,也就是為空了占遥,大家可以用兩個(gè)辦法處理
1俯抖、用 localStorage 來判斷是否存在token;

2瓦胎、每次服務(wù)端渲染芬萍,需要更新狀態(tài)樹 store 中的 token;

image

結(jié)語

今天的講解比較簡單搔啊,主要是驗(yàn)證邏輯我們之前也已經(jīng)提到了柬祠,在我們系列的 24 篇中,本文只是簡單的將其搬到我們的 nuxt 框架中來负芋,只不過中間還是會(huì)有一些小問題大家需要注意:

1漫蛔、插件 plugins 的使用很重要,2旧蛾、基于 axios 的 http 封裝莽龟,我只是寫了簡單的一個(gè) demo,復(fù)雜的大家可以找一些大的項(xiàng)目框架锨天,自行研究研究毯盈;3、路由機(jī)制也是需要留心的一個(gè)小知識(shí)點(diǎn)病袄,雖然不需要我們配置了搂赋,不過還是要了解內(nèi)部結(jié)構(gòu)赘阀。

好啦,nuxt 基本教程這里就說這么多吧脑奠,祝大家在大長假里開開森森噠~

GitHub

https://github.com/anjoy8/Blog.Vue.Nuxt

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末基公,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宋欺,更是在濱河造成了極大的恐慌轰豆,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齿诞,死亡現(xiàn)場離奇詭異秒咨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)掌挚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門嫌术,熙熙樓的掌柜王于貴愁眉苦臉地迎上來格嘁,“玉大人,你說我怎么就攤上這事总寒〕槊祝” “怎么了特占?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長云茸。 經(jīng)常有香客問我是目,道長,這世上最難降的妖魔是什么标捺? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任懊纳,我火速辦了婚禮,結(jié)果婚禮上亡容,老公的妹妹穿的比我還像新娘嗤疯。我一直安慰自己,他們只是感情好闺兢,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布茂缚。 她就那樣靜靜地躺著,像睡著了一般屋谭。 火紅的嫁衣襯著肌膚如雪脚囊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天桐磁,我揣著相機(jī)與錄音悔耘,去河邊找鬼。 笑死所意,一個(gè)胖子當(dāng)著我的面吹牛淮逊,可吹牛的內(nèi)容都是我干的催首。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼泄鹏,長吁一口氣:“原來是場噩夢啊……” “哼郎任!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起备籽,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤舶治,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后车猬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霉猛,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年珠闰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惜浅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伏嗜,死狀恐怖坛悉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情承绸,我是刑警寧澤裸影,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站军熏,受9級(jí)特大地震影響轩猩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荡澎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一均践、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衔瓮,春花似錦浊猾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至薇宠,卻和暖如春偷办,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背澄港。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工椒涯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人回梧。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓废岂,卻偏偏與公主長得像祖搓,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子湖苞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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