一步一步學Vue(七)


  前言:我以后在文章最后再也不說我下篇博文要寫什么,之前說的大家也可以忽略,如果你不忽略,會失望的😄,不過說出去的話還是要表示一下的,簡單介紹一下路由鈎子:

  正如其名,vue-router 提供的導航鈎子主要用來攔截導航,讓它完成跳轉或取消。有多種方式可以在路由導航發生時執行鈎子:全局的, 單個路由級的, 或者組件級的。

  1、全局鈎子

  使用 router.beforeEach 注冊一個全局的 before 鈎子:

var router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // TODO:處理跳轉邏輯
})
   to: Route: 即將要進入的目標 路由對象
  from: Route: 當前導航正要離開的路由
  next: Function: 一定要調用該方法來 resolve 這個鈎子。執行效果依賴 next 方法的調用參數。
  2、局部鈎子
  故名思意,單個路由項的配置鈎子函數:
var router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: AboutComponent,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

  3、組件級鈎子

  上篇中已經介紹了一個beforeRouteUpdate 用來解決路由改變但是組件重用的問題,除了這個鈎子函數,還包含
  • beforeRouteEnter
  • eforeRouteLeave
var Compoent = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被確認前調用
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,但是該組件被復用時調用,上篇文章已經使用過
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
  }
}

  Ok,上文留的坑表示完了,以后會繼續講的,主要沒有考慮好好的使用場景,就簡單的介紹一下了,這一篇文字內容會比較多,雖然我不太喜歡文字,但是沒辦法,說的少了反而說不清楚,見諒見諒。下文正式開始本篇主要內容。

  今天主要說一下前后端分離模式下的認證和授權,講這個也只是心血來潮,大家也可以放松的看一下,一起討論下方案,可以完善一下用於SPA解決方案。

  現在前后端分離模式盛行,如果不考慮SEO等影響,SPA不失為一種很好的方案,這里簡單的列一下其與傳統web開發區別:

  1、傳統web開發,每次請求都是請求完整的html,而spa每次都是局部請求並且是Ajax的;

  2、傳統web開發,數據和格式(data和html)是在服務器端拼接構建,直接返回到瀏覽器端直接渲染;而spa,則是請求html片段后請求數據,在客戶端通過客戶端模版引擎構建后渲染的;

  3、傳統web開發,前后端不分離,好多時候前端工作內容就是靜態頁面,所有的業務邏輯都在服務端;前后端分離后,大大增加前端的比重,一定程度上減輕了服務端的負擔,讓前端有了大前端的概念,讓前端升職加薪塊了很多,這是挑戰也是喜事兒,以后再也不會有人說前端是切頁面的了;

  4、spa開發模式,前后通過json交互,更加輕量級,后端接口對於前端來說就是數據服務;nodejs的出現,讓前端開發更往后了一層,有了前端的服務端(也就是中間層)的概念。

 

  我在做前后端分離架構時,一般的思路是:nginx作為前端服務器,並負責請求轉發(不加入node層,如果加入node層,可以直接去掉nginx),也就是兼反向代理服務器,后台通過rest接口提供服務;使用node或者nginx的好處是,可以很方便的處理跨域問題,如果不明白的,可百度或留言,今天網絡不給力,很多node模塊安裝不了,只能以偽代碼的方式講思路了,大家見諒。

  對於需要授權的服務我們需要覆蓋以下用例:

  1、用戶未登錄只能打開登錄頁面;

  2、用戶登錄信息有誤,登錄失敗

  3、用戶登錄信息正確,服務端分配token,用於請求rest接口

  4、用戶登錄后請求資源,可正常返回;

  5、用戶登錄后token過期,請求rest接口資源,返回401;

  6、附帶無效token請求資源,返回401

 

  針對上述用例,客戶端設計時需要完成如下幾個功能:

  1、注冊vue路由鈎子函數,beforeEnter,在每次路由跳轉前,進行路由檢查,判斷token是否存在;如果不存在,則打開到login頁面,如果存在,則可以執行路由next操作

  2、針對每次請求的ajax操作,攔截所有請求操作,加入token到http頭;攔截所有響應操作,對401等特殊狀態碼進行處理或者跳轉。

  客戶端可能的偽代碼如下:

var LoginComponent = {
    template: `
    
     <div class="login" >
        username:<input type="text" v-model="user.username" />
        password:<input type="password" v-model="user.password" />
        <input type="button" @click="login()" value="login" />
     </div>
    `,
    data: function () {
        return {
            user: {
                username: '',
                password: ''
            }
        }
    },
  //其它組件省略。。。

    methods: {
        /**
         * 登錄后保存token到localStorage
         */
        login: function () {
            ajaxPost('/login', this.user).then(res => {
                localStorage.setItem('token', res.data.token);
                //保存后執行跳轉,跳轉到路由query中傳遞的地址
            }, err => console.log(err))
        }
    }
}

var router = new VueRouter({
    //TODO:各種路由定義;
    routes: [
        {
            name: 'login', path: '/loin', component: LoginComponent
        }
    ]
});

//注冊全局事件鈎子
router.beforeEnter(function (to, from, next) {
    if (!localStorage.getItem('token')) {
        next({
            path: '/login',
            query: { redirect: to.fullPath }
        })
    } else {
        next();//如果存在token、則繼續前進
    }
});

 

 

  服務端需要做的工作:

  1、判斷是否是登錄請求,如果是登錄請求,不檢查http header中的token;驗證用戶信息,如果驗證通過,則創建token,設置過期時間並返回;如果驗證不通過,則返回錯誤信息即可;

  2、在非登錄請求的情況下(這里基於jwt生成token),獲取http header中token,如果獲取不到,則直接返回401,並提示token無效;獲取token后,使用服務端密鑰,對token進行解密,如果解密失敗,則說明token無效,返回401;如果解密成功,則判斷是否過期,如果已過期,則返回401,並提示token已過期。(jwt一般會使用「sub,exp,iat等字段;其中包含了主題部分,創建時間戳等各種,可以滿足絕大多數場景」)

  服務端可能的偽代碼如下(基於Express 4.x):

var express = require("express");

var app = express();

//鑒權中間件
app.use(function (req, res, next) {
    if (req.path === '/login') {
        //TODO:進行登錄驗證,並響應token
        res.json({
            success: true,
            data: {
                token: 'xxxxxx'
            }
        })
    } else {
        var token = req.headers['Authorization'];
        //TODO:判斷請求是否合法
        //如果不合法,這里直接返回401 ,並提示信息
        if (!valid(token)) {
            res.status(401)
        } else {
            //如果合法 執行next操作
            next();
        }

    }
});

//其它路由服務
//app.get('xxxx')
//...其它路由服務

app.listen(80,function(){
    console.log("port 80 is listenning!!!");
})

  上面的代碼經過完善后是可以運行的,今天時間比較倉促,就寫這么多吧,雖然我不准備說一下篇的內容是什么,但是下一篇至少要完成這個認證的demo的,對於node平台的基礎知識希望讀者有一個簡單的了解,這樣對后台的處理也會有幫助。

  ps:今天家里網絡超級慢,下載一個express模塊近三個小時,重試了好幾次,還是不行,放棄了。下雨網絡也慢,服了。。。

  

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM