Vuex身份認證

雖說上一節我們實現了登錄功能,但是實際上還是可以通過瀏覽器的地址來跳過登錄訪問到后臺,這種可有可無的登錄功能使得系統沒有安全性,而且沒有意義
為了讓登錄這個功能有意義,我們應該:

  • 應當在用戶登錄成功之后給用戶生成一個標記(令牌),將這個令牌保存起來
  • 在用戶訪問任意需要登錄的頁面(組件)的時候都要去驗證令牌
  • 從而識別到用戶是否登錄或者是否有權限去訪問對應的功能
    1.成功時,訪問組件
    2.失敗時,進行提示
    如何讓login組件中的數據被任意其他組件訪問呢?這個時候可以使用vue官方的狀態管理工具Vuex

Vuex

Vuex是一個專門為Vue.js應用程序開發的狀態管理模式
文檔:

https://vuex.vuejs.org/zh

  • Vuex是專門為Vue.js設計的狀態管理庫
  • 采用集中式的方式存儲需要共享的數據
  • 本質上就是一個JavaScript庫
  • 用來解決復雜組件通信,數據共享的問題
    簡單來說就是Vuex用來統一存儲需要在多個組件間共享的狀態(數據),狀態可以被任意組件操作,使得組件通信變得易如反掌

那么歸根到底,我們是否需要Vuex,要根據什么來判斷呢?

  • 多個視頻依賴于同一個狀態
  • 來自不同視圖的行為需要變更同一狀態
    安裝Vuex
    通過npm安裝:
npm install vuex -S

使用Vue CLI創建項目的時候,可以在項目選項中選擇Vuex,這個時候就不需要再單獨安裝了,這邊我們已經在創建項目的時候安裝過了Vuex,所以不再多做操作

使用

創建Vuex實例store,store通常稱之為"容器"
文件,store/index.js



main.js導入,根Vue實例中引入Vuex作為插件

通過Vue.use()引入Vuex中,Vuex的功能被注入到根實例下的所有子組件中,可以通過$store訪問到內部功能
我們的項目通過VueCLI創建時已經選擇了Vuex,所以創建和引入都已經被Vue CLI自動完成了

State

容器中的state用于存儲需要在組件之間共享的數據

  • 容器中的數據可以被任意組件訪問
  • 容器中的數據為響應式數據
    state存儲count

    Vue官方調試工具也可以看到數據

    在組件中,通過vm.$store.state.狀態名訪問
// login/index.vue
methods: {async onSubmit () {console.log(this.$store.state.user)...}
}

Mutation

來源:官方文檔

簡單來說,要修改Vuex的state,必須提前定義Mutation函數,需要的時候再進行提交,Mutation接收state對象作為第一個參數,用于操作state內部的數據

// store/index.js
export default new Vuex.Store({state: {user: 100},mutations: {setUser (state) {state.user++}},actions: {},modules: {}
})

在組件中通過vm.$store.commit('Mutation名稱')提交Mutation,執行操作

// login/index.vue
methods: {async onSubmit () {console.log(this.$store.state.user)this.$store.commit('setUser')console.log(this.$store.state.user)...}
}

Mutation還接受提交載荷(payload)作為第二個參數,指的是commit()傳入的額外數據,常常需要根據上下文數據修改state使用

// store/index.js
mutations: {setUser (state, payload) {state.user = payload}
},
// login/index.vue
methods: {async onSubmit () {this.$store.commit('setUser', '示例內容')...}
}

但是實際上在大多數情況下,載荷應該是一個對象才對,這樣就可以包含多個字段并且記錄的mutation會更易讀:

mutations: {increment (state, payload) {state.count += payload.amount}
}
store.commit('increment', {amount: 10
})
文檔中的另一種對象風格的提交方式,可以記錄一下

Mutation的設置方式使得Vuex的狀態修改有跡可循,易于維護,如果state可以通過賦值修改,一旦出錯了就找不到錯誤點了
除此之外,Vue Devtools還提供了Vuex更高級的調試方式Time Travel

可以回溯到特定的操作點上進行調試

Mutation必須為同步函數,由于DevTools提供了Mutation日志功能,為了確保功能正常,內部不能存在異步任務,否則DevTools將無法得知Mutation的準確調用順序,如果需要進行異步操作,那么則需要Vuex的Action

Action

Action類似于Mutation,不同的地方在于:

  • Action提交的是Mutation,而不是直接變更狀態
  • Action可以包含任意的異步操作
    Action 函數接受一個與store實例具有相同方法和屬性的context對象,因為可以調用context.commit提交一個Mutation
// store/index.js
actions: {addAction (context) {setTimeout(function () {context.commit('setUser')}, 1000)}
},

在實機操作中,我們經常用到ES2015的參數結構來簡化代碼(就比如我們在解構后端傳來的數據一樣,直接{ data }),這種情況尤其是出現在我們需要多次調用commit的時候

  actions: {// jia (context) {//   context.commit('jia')// }jia ({ commit }) {commit('jia')}},

Action 通過 vm.$store.dispatch方法觸發,參數1為action名稱,參數2為payload

// login/index.vue
methods: {async onSubmit () {this.$store.dispatch('addAction')...}
}

Vuex 核心概念還有Getter和Module,可以通過文檔來進行學習

身份認證

登錄狀態存儲

獲取能夠在任意組件中訪問用戶的登錄信息,我們將狀態存儲在Vuex中

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {user: null},mutations: {setUser (state, payload) {state.user = payload}},actions: {},modules: {}
})

聲明Mutation拿來用于修改user數據,具體內容采用payload載荷方式傳入,我們可以通過devtools調試工具查看
觀察到通過接口傳來的數據,我們應該拿來存入的是data.content,內部為用戶的相關信息。

// login/index.js
methods: {async onSubmit () {try {...// 當登錄成功時,記錄登錄狀態,存儲到 Vuex 中this.$store.commit('setUser', data.content)this.$router.push({name: 'home'})this.$message.success('登錄成功')} catch (err) {console.log('驗證失敗', err)}}
}

那么又因為傳來的數據是JSON格式,為了以后方便我們的使用,我們應該在Mutation的setUser中轉換為對象保存,可以通過DevTools調試工具查看到,然后就是通過本地存儲的方式對user進行數據持久化,避免頁面刷新后丟失,存儲成功之后呢,就可以將user的初始值更改為本地存儲獲取user的數據

  state: {// 用于登錄成功后保存用戶信息的(初始值嘗試讀取本地存儲user: JSON.parse(window.localStorage.getItem('user') || null)},mutations: {// 存儲用戶數據setUser (state, payload) {// 將payload轉換為對象后進行存儲state.user = JSON.parse(payload)// 將payload的數據添加到本地存儲中// 本地存儲只能存儲字符串window.localStorage.setItem('user', payload)}},

校驗頁面訪問權限

路由跳轉時,需要校驗登錄狀態,根據結果進行后續處理
這里使用Vue Router的導航守衛beforeEach,在任務導航被觸發的時候進行登錄狀態監測,當前后臺頁面都需要登錄狀態,但是有些頁面不需要登錄狀態的話,這個該如何處理呢?
使用:Vue Router的路由元信息功能來設置
下面給需要設置登錄狀態的路由添加路由元信息(比如我們把home頁面的子路由的部分設置為需要登錄)

  • meta用于保存與路由相關的自定義數據
  • requiresAuth表示是否需要認證,true為需要



    用戶登錄狀態保存在store(Vuex)中,需要引入文件來讀取數據檢測,在導航守衛中檢測to的路由是否需要登錄

// 全局前置守衛
router.beforeEach((to, from, next) => {// 驗證 to 路由記錄是否需要進行身份認證if (to.matched.some(record => record.meta.requiresAuth)) {// 驗證Vuex 的 store 中的用戶信息是否存儲if (!store.state.user) {// 未登錄,跳轉到登錄頁面return next({ name: 'login' })}// 已經登錄,允許通過next()} else {// 無需登錄,允許通過next() // 確保一定要調用 next()}
})

登錄后跳轉到上次訪問頁面

上一次我如果訪問了用戶管理/user,過了一段時間狀態過期,直接訪問路由/user,跳轉到login,登陸之后又跳轉了首頁。如果我希望登錄后直接跳轉到user而不是首頁,我們就應該在每次跳轉到/login時記錄當前to目標的路由信息,這個時候就可以通過跳轉路由的query屬性進行設置

//router/index.jsif (!store.state.user) {// 未登錄,跳轉到登錄頁面next({name: 'login',query: {// 將本次路由的fullpath傳遞給login頁面// path僅包含路徑,fullpath為完整url(包含了查詢字符串參數等信息)redirect: to.fullPath}})}

那么在登錄頁中,登陸成功的跳轉時,應該檢測是否存在登錄前的頁面信息,有就跳轉,沒有就默認跳轉首頁


變更了一下push順序,防止出現路由重定向提前

除了登錄過期以外,例如將頁面存儲書簽,或者點擊其他人發送的鏈接訪問,都可以在登陸之后自動跳轉到對應的路由,提高了我們的體驗


刪除掉本地用戶信息后使用對應路由打開網頁就可以在登錄后定向到指定的路由了

用戶信息與接口鑒權

用戶基本信息接口:接口
首先使用postman進行接口測試
在集合中添加一個新的請求,設置基本信息


發送請求,發現傳回來的是錯誤信息
HTTP狀態碼是401,狀態文本為'Unauthorized'未授權

這個時候就說明接口需要授權才能訪問,查詢了接口的說明文檔可以得知,需要一個名為“Authotization”的請求參數(位于請求頭),用于驗證 授權信息,這種驗證接口的授權的處理方式我們稱之為接口鑒權

得出兩條結論:

  • 后端提供的接口是沒法隨便訪問的
  • 使用接口前需要進行接口的鑒權處理
    那么我們該怎么獲得權限去獲取后端返回的數據呢?

Token

一種常用的接口鑒權方式
Token是在用戶登陸成功之后,由服務端生成的一段保存了用戶身份信息,加密的字符串
生成之后,通過響應方式將token信息響應到服務端,通過之前的登錄接口響應成功時可以看到

將其復制下來,保存到用戶基本信息接口的請求頭上

請求頭Authorization

就能得到信息啦,接口鑒權成功

Postman統一設置token

后續我們要用到的這個集合的接口會更多,每次都寫Token的話就要被煩到,所以我們可以使用Postman提供的統一設置方式





保存了之后,回到用戶信息接口會發現我們單獨設置的authorization提示了已經被統一設置的信息,我們就可以將自己設置的給刪除掉,再次發送請求也是沒有問題的

實現用戶信息展示

測試處理完畢之后,我們需要在代碼中進行Token處理和功能實現
首先要封裝用于用戶信息請求的方法,在header最后那個設置Token,引入store用于讀取token



接著在app-header組件中引入功能,并且在created鉤子函數中請求數據,并將其數據綁定到視圖中

<script>
// 引入用戶信息接口功能
import { getUserInfo } from '@/services/user'export default {name: 'AppHeader',created () {// 加載用戶信息// 鉤子函數不建議書寫代碼邏輯,最好直接使用封裝好的函數this.loadUserInfo()},data () {return {// 用戶信息userInfo: {}}},methods: {async loadUserInfo () {const { data } = await getUserInfo()// console.log(data)this.userInfo = data.content}}
}
</script>
綁定數據

通過請求攔截器設置Token

通過Axios的請求攔截器進行統一設置Token
很多請求都是需要在header設置Token信息的,可以通過Axios攔截器進行統一處理
Axios攔截器與導航守衛相似,可以在任意請求和響應前進行攔截處理,功能分為:

  • 請求攔截器
  • 響應攔截器
    通過請求攔截器參數config.headers可以訪問請求頭,將store中的Token統一設置就可以了
// 設置請求攔截器
request.interceptors.request.use(function (config) {
// 判斷config.url的前綴是什么,然后進行請求baseURL的設置config.baseURL = getBaseURL(config.url)// 統一的token信息設置// 為了嚴謹,可以讀取store中的user后進行Token檢測const { user } = store.stateif (user && user.access_token) {// 設置tokenconfig.headers.Authorization = user.access_token}return config
})

這個攔截器設置之后呢,services/user.js中的getUserInfo內部的Token設置就可以刪除了,同時也可以去掉store的引入

// services/user.js
...
// import store from '@/store'
...
// 用戶基本信息請求
export const getUserInfo = () => {return request({method: 'GET',url: '/front/user/getInfo'// 在 header 中設置 Token 信息(統一設置后去除,記得去除上一行的分號)/* headers: {Authorization: store.state.user.access_token} */})
}

用戶退出

首先我們要給退出按鈕設置點擊事件,發現其實是觸發不了的,那是因為我們使用的是Element組件,這里的退出按鈕是組件,而組件設置的都是自定義事件

// app-header.vue
<el-dropdown-itemdivided@click="handleLogout"
>退出</el-dropdown-item>...methods: {...// 退出按鈕功能handleLogout () {console.log('點擊退出')}
}

我們可以使用事件修飾符.native來監聽組件根元素的原生事件

// app-header.vue
<el-dropdown-itemdivided@click.native="handleLogout"
>退出</el-dropdown-item>

點擊退出后,清除store內部的用戶信息,同時跳轉回到登錄頁面

  • 通過mutation中的setUser清空user,由于setUser也設置了本地存儲,這個時候也會自動清空
// 退出功能handleLogout () {// 清除store的用戶信息this.$store.commit('setUser', null)// 跳轉登錄頁this.$router.push('/login')}

可以通過Element的MessageBox彈框組件進行退出確認提示,增強體驗感

  • 確認提示使用&confirm(),確定觸發then(),取消觸發catch()
  • 按鈕內容默認為確定和取消,如不更改可以刪除
    在點擊退出按鈕時,通過this,$confirm()進行確認消息設置
  • 將前面設置的退出功能移步到位確認退出的代碼區域
// 退出功能handleLogout () {this.$confirm('確認退出嗎?', '退出提示', {confirmButtonText: '確定',cancelButtonText: '取消',type: 'warning'}).then(() => {// 清除store的用戶信息this.$store.commit('setUser', null)// 跳轉登錄頁this.$router.push('/login')this.$message({type: 'success',message: '退出成功!'})}).catch(() => {this.$message({type: 'info',message: '取消退出'})})}

以上,登錄功能到認證到退出一個閉環功能完成了,完善程度很高



喜歡的朋友記得點贊、收藏、關注哦!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87646.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87646.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87646.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springboot中使用線程池

1.什么場景下使用線程池&#xff1f; 在異步的場景下&#xff0c;可以使用線程池 不需要同步等待&#xff0c; 不需要管上一個方法是否執行完畢&#xff0c;你當前的方法就可以立即執行 我們來模擬一下&#xff0c;在一個方法里面執行3個子任務&#xff0c;不需要相互等待 …

Flask+LayUI開發手記(十):構建統一的選項集合服務

作為前端最主要的組件&#xff0c;無論是layui-table表格還是layui-form表單&#xff0c;其中都涉及到選項列的處理。如果是普通編程&#xff0c;一個任務對應一個程序&#xff0c;自然可以就事論事地單對單處理&#xff0c;前后端都配制好選項&#xff0c;手工保證兩者的一致性…

redis的數據初始化或增量更新的方法

做系統開發的時候&#xff0c;經常需要切換環境&#xff0c;做一些數據的初始化的工作&#xff0c;而redis的初始化&#xff0c;假如通過命令來執行&#xff0c;又太復雜&#xff0c;因為redis有很多種數據類型&#xff0c;全部通過敲擊命令來初始化的話&#xff0c;打的命令實…

【PaddleOCR】OCR表格識別數據集介紹,包含PubTabNet、好未來表格識別、WTW中文場景表格等數據,持續更新中......

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

sparkjar任務運行

mainclass&#xff1a; test.sparkjar.SparkJarTest

Web攻防-文件下載文件讀取文件刪除目錄遍歷路徑穿越

知識點&#xff1a; 1、WEB攻防-文件下載&讀取&刪除-功能點&URL 2、WEB攻防-目錄遍歷&穿越-功能點&URL 黑盒分析&#xff1a; 1、功能點 文件上傳&#xff0c;文件下載&#xff0c;文件刪除&#xff0c;文件管理器等地方 2、URL特征 文件名&#xff1a; d…

使用LIMIT + OFFSET 分頁時,數據重復的風險

在使用 LIMIT OFFSET 分頁時&#xff0c;數據重復的風險不僅與排序字段的唯一性有關&#xff0c;還與數據變動&#xff08;插入、刪除、更新&#xff09;密切相關。以下是詳細分析&#xff1a; 一、數據變動如何導致分頁異常 1. 插入新數據 場景&#xff1a;用戶在瀏覽第 1 頁…

Excel 數據透視表不夠用時,如何處理來自多個數據源的數據?

當數據透視表感到“吃力”時&#xff0c;我們該怎么辦&#xff1a; 數據量巨大&#xff1a;Excel工作表有104萬行的限制&#xff0c;當有幾十萬行數據時&#xff0c;透視表和公式就會變得非常卡頓。數據來源多樣&#xff1a;數據分散在多個Excel文件、CSV文件、數據庫甚至網頁…

cf(1034)Div3(補題A B C D E F)

哈&#xff0c;這個比賽在開了不久之后&#xff0c;不知道為啥卡了差不多20來分鐘&#xff0c;后面卡著卡著就想睡覺了。實在是太困了.... 題目意思&#xff1a; Alice做一次操作&#xff0c;刪除任意數字a,而Bob做一次操作刪除b使得ab對4取余是3。 獲勝條件&#xff0c;有人…

瀏覽器與服務器的交互

瀏覽器地址欄輸入URL&#xff08;網址??&#xff09; ????(1) 服務器進行URL解析??&#xff1a;驗證URL格式&#xff0c;提取協議、域名等 ????(2) 服務器進行DNS查詢??&#xff1a;將域名轉換為IP地址&#xff08;可能涉及緩存或DNS預取&#xff09; ????…

Spring Boot中POST請求參數校驗的實戰指南

在現代的Web開發中&#xff0c;數據校驗是確保應用程序穩定性和安全性的關鍵環節。Spring Boot提供了強大而靈活的校驗機制&#xff0c;能夠幫助開發者輕松地對POST請求參數進行校驗。本文將詳細介紹如何在Spring Boot中實現POST請求參數的校驗&#xff0c;并通過具體的代碼示例…

Spring Boot + MyBatis/MyBatis Plus:XML中循環處理List參數的終極指南

重要提醒&#xff1a;使用Param注解時&#xff0c;務必導入正確的包&#xff01; import org.apache.ibatis.annotations.Param; 很多開發者容易錯誤導入Spring的Param&#xff0c;導致參數綁定失敗&#xff01; 一、為什么需要傳遞List參數&#xff1f; 最常見的場景是動態構…

Design Compiler:自適應重定時(Adaptive Retiming)

相關閱讀 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 簡介 重定時是DC Ultra引入的一種時序優化技術&#xff0c;可以將時序單元&#xff08;觸發器和鎖存器&#xff09;穿越組合邏輯前后移動&#xff0c;以優化設…

解決kali Linux在VMware中的全局縮放問題

在每次啟動kali時&#xff0c;因為屏幕分辨率過高&#xff0c;系統整體特別小&#xff0c;該怎么操作調整合適呢 在搜索中搜索kali HiDPI Mode 選擇yes 然后就會自動調整合適了

Python關鍵字梳理

在 Python 中&#xff0c;關鍵字&#xff08;Keywords&#xff09;是具有特殊含義的保留字&#xff0c;它們用于定義語法和結構。async 是 Python 3.5 引入的關鍵字&#xff0c;用于支持異步編程&#xff08;Asynchronous Programming&#xff09;。下面我將詳細講解 async 及其…

結構體實戰:用Rust編寫矩形面積計算器

文章目錄結構體實戰&#xff1a;用Rust編寫矩形面積計算器&#x1f4d0; 問題描述1?? 基礎版&#xff1a;獨立變量&#xff08;混亂版&#xff09;2?? 進階版&#xff1a;使用元組3?? 終極版&#xff1a;使用結構體&#xff08;優雅版&#xff09;&#x1f3af; 運行結果…

基于開源鏈動2+1模式AI智能名片S2B2C商城小程序的場景零售創新研究

摘要&#xff1a;本文聚焦場景消費邏輯&#xff0c;探討開源鏈動21模式AI智能名片S2B2C商城小程序在場景零售中的應用。通過分析場景消費中消費者體驗的關鍵作用&#xff0c;結合該技術組合的特性&#xff0c;闡述其如何優化場景內容、增強場景美感&#xff0c;為消費者創造超乎…

新發布:26考研院校和專業大綱

復習方向錯了&#xff0c;努力可能白費 近日&#xff0c;多所高校陸續發布2026年碩士研究生招生考試自命題科目大綱&#xff0c;為備考的學子們指明了復習方向。今年的考綱有哪些重要變化&#xff1f;又該如何應對&#xff1f;本文為你全面梳理&#xff01; 院校和專業發布詳情…

matlab/Simulink-全套50個汽車性能建模與仿真源碼模型9

50個simulink模型&#xff08;所有模型羅列如下&#xff0c;沒羅列就是沒有&#xff0c;包含子模塊總共50個。&#xff09; 基于汽車驅動力-行駛阻力平衡圖的汽車動力性仿真模型 基于汽車動力特性圖的汽車動力性仿真模型 基于汽車功率平衡圖的汽車動力性仿真模型 電動汽車動力…

為什么星敏感器(Star Tracker)需要時間同步?—— 從原理到應用的全解析

為什么星敏感器&#xff08;Star Tracker&#xff09;需要時間同步&#xff1f;—— 從原理到應用的全解析 引言 在衛星姿態控制系統中&#xff0c;星敏感器&#xff08;Star Tracker, 簡稱“星敏”&#xff09; 是最精確的姿態測量設備之一&#xff0c;其精度可達角秒級&…