使用Vuex解決Vue中的身份驗(yàn)證問(wèn)題

傳統(tǒng)方式中,許多人使用本地存儲(chǔ),來(lái)管理通過(guò)客戶端驗(yàn)證生成的tokens。一個(gè)大問(wèn)題是如何有更好的方式,來(lái)管理驗(yàn)證tokens,從而允許我們來(lái)存儲(chǔ)更大的用戶信息。

寧都網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)于2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。

這就是Vuex的作用。 Vuex為Vue.js應(yīng)用管理狀態(tài).。對(duì)于應(yīng)用中所有的組件來(lái)說(shuō),它被當(dāng)做中央存儲(chǔ),并用規(guī)則確保狀態(tài)只能以可預(yù)見(jiàn)的方式改變。

對(duì)于經(jīng)常檢查本地存儲(chǔ)來(lái)說(shuō),聽(tīng)起來(lái)是個(gè)更好的選擇?讓我們一起來(lái)探索下吧。

建立應(yīng)用模塊

對(duì)于這個(gè)項(xiàng)目,我們想創(chuàng)建一個(gè)使用vuex和vue-router的vue應(yīng)用。我們會(huì)使用vue cli 3.0 來(lái)創(chuàng)建一個(gè)vue項(xiàng)目,并從選項(xiàng)中選擇路由和vuex。

執(zhí)行下面的命令開(kāi)始創(chuàng)建:

$ vue create vue-auth

按照對(duì)話框的提示,添加必要的信息,并選擇我們需要的選項(xiàng),完成安裝。

下一步, 安裝axios:

$ npm install axios --save 

配置Axios

我們?cè)谠S多組件中都需要用到axios。讓我們?cè)谌终w來(lái)配置它,這樣當(dāng)我們需要它的時(shí)候,不用每次都去引入。

打開(kāi) ./src/main.js 文件,并且添加下面:

[...]
import store from './store'
import Axios from 'axios'
 
Vue.prototype.$http = Axios;
const token = localStorage.getItem('token')
if (token) {
 Vue.prototype.$http.defaults.headers.common['Authorization'] = token
}
[...]

現(xiàn)在,當(dāng)我們想在組件內(nèi)使用axios時(shí), 我們可以用this.$http ,這樣相當(dāng)于直接是axios。我們也可以在axios頭部給自己的token, 設(shè)置身份驗(yàn)證,這樣如果token是必需的,我們的請(qǐng)求將處于控制中。在這種方式下,當(dāng)我們想要發(fā)送請(qǐng)求時(shí),任何時(shí)候都不用設(shè)置token。

相關(guān)課程: Vue創(chuàng)建一個(gè)網(wǎng)上商店

完成之后,讓我們使用服務(wù)器來(lái)處理身份驗(yàn)證。

創(chuàng)建身份驗(yàn)證服務(wù)

我已經(jīng)寫過(guò)關(guān)于這個(gè),在我解釋如何用vue-router來(lái)解決身份驗(yàn)證時(shí)。仔細(xì)看看Setup Node.js Server 這個(gè)章節(jié)。

創(chuàng)建組件

登錄組件

創(chuàng)建Login.vue ./src/components 目錄下。 之后, 給登錄頁(yè)面添加模板:

<template>
 <div>
 <form class="login" @submit.prevent="login">
  <h2>Sign in</h2>
  <label>Email</label>
  <input required v-model="email" type="email" placeholder="Name"/>
  <label>Password</label>
  <input required v-model="password" type="password" placeholder="Password"/>
  <hr/>
  <button type="submit">Login</button>
 </form>
 </div>
</template>

當(dāng)你做完之后, 添加data屬性,將其綁定到HTML表單中:

[...]
<script>
 export default {
 data(){
  return {
  email : "",
  password : ""
  }
 },
 }
</script>

現(xiàn)在, 讓我們給登錄添加方法:

[...]
<script>
 export default {
 [...]
 methods: {
  login: function () {
  let email = this.email 
  let password = this.password
  this.$store.dispatch('login', { email, password })
  .then(() => this.$router.push('/'))
  .catch(err => console.log(err))
  }
 }
 }
</script>

我們正在使用vuex的action — login 來(lái)解決身份驗(yàn)證。我們可以在將actions細(xì)化到回調(diào)里面,這樣就可以在自己的組件里面做一些很酷的事情了。

注冊(cè)組件

跟login組件類似,那我們給注冊(cè)用戶弄一個(gè)了。在組件目錄里面創(chuàng)建Register.vue ,并將下面的添加進(jìn)去:

<template>
 <div>
 <h5>Register</h5>
 <form @submit.prevent="register">
  <label for="name">Name</label>
  <div>
   <input id="name" type="text" v-model="name" required autofocus>
  </div>
  <label for="email" >E-Mail Address</label>
  <div>
   <input id="email" type="email" v-model="email" required>
  </div>
  <label for="password">Password</label>
  <div>
   <input id="password" type="password" v-model="password" required>
  </div>
  <label for="password-confirm">Confirm Password</label>
  <div>
   <input id="password-confirm" type="password" v-model="password_confirmation" required>
  </div>
  <div>
   <button type="submit">Register</button>
  </div>
 </form>
 </div>
</template>

讓我們定義一下這些將綁定到表單里面的data屬性:

[...]
<script>
 export default {
 data(){
  return {
  name : "",
  email : "",
  password : "",
  password_confirmation : "",
  is_admin : null
  }
 },
 }
</script>

現(xiàn)在,讓我們添加方法進(jìn)去:

[...]
<script>
 export default {
 [...]
 methods: {
  register: function () {
  let data = {
   name: this.name,
   email: this.email,
   password: this.password,
   is_admin: this.is_admin
  }
  this.$store.dispatch('register', data)
  .then(() => this.$router.push('/'))
  .catch(err => console.log(err))
  }
 }
 }
</script> 

安全組件

讓我們創(chuàng)建一個(gè)普通的組件,它在用戶通過(guò)驗(yàn)證后會(huì)顯示。文件命名為Secure.vue,并添加下面的進(jìn)去:

<template>
 <div>
 <h2>This page is protected by auth</h2>
 </div>
</template>

更新App組件

打開(kāi)./src/App.vue 文件,并添加下面的進(jìn)去:

<template>
 <div id="app">
 <div id="nav">
  <router-link to="/">Home</router-link> |
  <router-link to="/about">About</router-link><span v-if="isLoggedIn"> | <a @click="logout">Logout</a></span>
 </div>
 <router-view/>
 </div>
</template>

如果用戶登錄進(jìn)去后,你能看到關(guān)聯(lián)的Logout了 嗎?很好。

現(xiàn)在,讓我們給logout添加邏輯。

<script>
 export default {
 computed : {
  isLoggedIn : function(){ return this.$store.getters.isLoggedIn}
 },
 methods: {
  logout: function () {
  this.$store.dispatch('logout')
  .then(() => {
   this.$router.push('/login')
  })
  }
 },
 }
</script>

當(dāng)用戶點(diǎn)擊退出按鈕時(shí),我們其實(shí)在做兩件事 — 計(jì)算用戶驗(yàn)證的狀態(tài)和分發(fā)vuex store里面的退出事件。在退出之后,我們利用 this.$router.push('/login'),切換用戶到 login頁(yè)面。當(dāng)然你可以改變?nèi)魏文阆胱層脩籼D(zhuǎn)的地方。

就是這樣了。讓我們用vuex構(gòu)建權(quán)限模塊。

Vuex權(quán)限模塊

如果你讀過(guò)以前的Setup Node.js Server **部分, 你應(yīng)該注意到我們需要在本地存儲(chǔ)用戶權(quán)限token,同時(shí),當(dāng)用戶被授予權(quán)限后,我們隨時(shí)需要重新得到token以及用戶信息。

首先, 讓我們給vuex創(chuàng)建 store.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
 state: {
 status: '',
 token: localStorage.getItem('token') || '',
 user : {}
 },
 mutations: {
 },
 actions: {
 },
 getters : {
 }
})

如果你注意到,我們同時(shí)引入了vue,vuex和axios,之后讓vue使用vuex,這是因?yàn)樗呛苤匾囊徊健?/p>

我們已經(jīng)定義了state的屬性?,F(xiàn)在vuex的state能夠支持驗(yàn)證狀態(tài), jwt token以及用戶信息。

創(chuàng)建Vuex登錄事件

Vuex actions里面主要是提交更改到vuex的store里面。我們將創(chuàng)建一個(gè)login 的action,它將使用服務(wù)器對(duì)用戶進(jìn)行身份驗(yàn)證,并向vuex存儲(chǔ)提交用戶憑據(jù)。打開(kāi)./src/store.js文件,并添加下面到actions對(duì)象中:

login({commit}, user){
 return new Promise((resolve, reject) => {
  commit('auth_request')
  axios({url: 'http://localhost:3000/login', data: user, method: 'POST' })
  .then(resp => {
  const token = resp.data.token
  const user = resp.data.user
  localStorage.setItem('token', token)
  axios.defaults.headers.common['Authorization'] = token
  commit('auth_success', token, user)
  resolve(resp)
  })
  .catch(err => {
  commit('auth_error')
  localStorage.removeItem('token')
  reject(err)
  })
 })
},

登錄action通過(guò)vuex commit驗(yàn)證,我們將用它進(jìn)行觸發(fā)更改。vuex store里面能記錄這些更改的變化。

我們正在調(diào)用服務(wù)器的登錄路徑并返回必要的數(shù)據(jù)。我們?cè)诒镜卮鎯?chǔ)token,之后通過(guò)auth_success來(lái)更新存儲(chǔ)用戶信息和token。在這一點(diǎn)上,我們也在頭部設(shè)置了axios 。

我們可以在vuex store中存儲(chǔ)token,但是如果用戶離開(kāi)我們的應(yīng)用,所有在vuex里面的存儲(chǔ)都將消失。為了確保用戶在有效時(shí)間內(nèi)不用再重復(fù)登錄,我們只能將token進(jìn)行本地存儲(chǔ)。

重要的是你知道這些是如何工作的,這樣你就能決定你到底想要實(shí)現(xiàn)什么。

我們返回一個(gè)promise,這樣我們能在用戶登錄完成后,做出響應(yīng)。

創(chuàng)建Vuex注冊(cè)事件

像 login 事件, the register 事件是同一種工作方式。在相同的文件中,添加下面的到actions對(duì)象里面:

register({commit}, user){
 return new Promise((resolve, reject) => {
 commit('auth_request')
 axios({url: 'http://localhost:3000/register', data: user, method: 'POST' })
 .then(resp => {
  const token = resp.data.token
  const user = resp.data.user
  localStorage.setItem('token', token)
  axios.defaults.headers.common['Authorization'] = token
  commit('auth_success', token, user)
  resolve(resp)
 })
 .catch(err => {
  commit('auth_error', err)
  localStorage.removeItem('token')
  reject(err)
 })
 })
},

它與login 事件工作方式很像,。稱之為有共同的mutators的 login 和register ,具有相同的目標(biāo)——讓用戶進(jìn)入系統(tǒng)。

創(chuàng)建Vuex退出事件

我們希望用戶能夠退出系統(tǒng),同時(shí),我們希望銷毀上一次驗(yàn)證的會(huì)話數(shù)據(jù)。在同一個(gè)actions對(duì)象中,添加下面:

logout({commit}){
 return new Promise((resolve, reject) => {
 commit('logout')
 localStorage.removeItem('token')
 delete axios.defaults.headers.common['Authorization']
 resolve()
 })
}

現(xiàn)在,當(dāng)用戶點(diǎn)擊退出時(shí),我們將移除之前在 axios頭部設(shè)置的jwt token 。他們現(xiàn)在將無(wú)法執(zhí)行需要token的事務(wù)。

創(chuàng)建Mutations

像我之前提到的,mutators是被用來(lái)改變vuex store的狀態(tài)。讓我們?cè)趹?yīng)用中給用過(guò)的mutators定義。在mutators對(duì)象中,添加下面的:

mutations: {
 auth_request(state){
 state.status = 'loading'
 },
 auth_success(state, token, user){
 state.status = 'success'
 state.token = token
 state.user = user
 },
 auth_error(state){
 state.status = 'error'
 },
 logout(state){
 state.status = ''
 state.token = ''
 },
},

創(chuàng)建Getters

我們使用getter來(lái)獲取vuex狀態(tài)中的屬性值。在這種情況下,getter的作用是將應(yīng)用程序數(shù)據(jù)與應(yīng)用程序邏輯分離,并確保我們不會(huì)泄露敏感信息。

添加下面的到getters 對(duì)象中:

getters : {
 isLoggedIn: state => !!state.token,
 authStatus: state => state.status,
}

你會(huì)同意我的觀點(diǎn),這是一種更簡(jiǎn)潔的訪問(wèn)存儲(chǔ)數(shù)據(jù)的方式☺️.

在Auth后面隱藏頁(yè)面

這篇文章的整個(gè)目的是實(shí)現(xiàn)身份驗(yàn)證,讓沒(méi)有權(quán)限的用戶看不到某些頁(yè)面。為了實(shí)現(xiàn)這個(gè),我們需要知道用戶想要訪問(wèn)的頁(yè)面,以及當(dāng)用戶被授權(quán)時(shí),我們有一定的方法來(lái)檢驗(yàn)它。我們同時(shí)需要一定的方式,如果某些頁(yè)面,授權(quán)或者未授權(quán)的用戶可以單獨(dú)或者同時(shí)訪問(wèn)的。這些都是很重要的考慮條件,幸運(yùn)地是,我們可以通過(guò)vue-router來(lái)說(shuō)實(shí)現(xiàn)。

定義路由給授權(quán)和未授權(quán)的頁(yè)面

打開(kāi) ./src/router.js 文件,并引入我們需要的這些:

import Vue from 'vue'
import Router from 'vue-router'
import store from './store.js'
import Home from './views/Home.vue'
import About from './views/About.vue'
import Login from './components/Login.vue'
import Secure from './components/Secure.vue'
import Register from './components/Register.vue'

Vue.use(Router)

正如你看到的這樣,我們已經(jīng)引入vue,vue-router和我們創(chuàng)建的vuex。我們同時(shí)還引入了定義的所有組件,并設(shè)置vue中使用路由。

讓我們定義路由:

[...]
let router = new Router({
 mode: 'history',
 routes: [
 {
  path: '/',
  name: 'home',
  component: Home
 },
 {
  path: '/login',
  name: 'login',
  component: Login
 },
 {
  path: '/register',
  name: 'register',
  component: Register
 },
 {
  path: '/secure',
  name: 'secure',
  component: Secure,
  meta: { 
  requiresAuth: true
  }
 },
 {
  path: '/about',
  name: 'about',
  component: About
 }
 ]
})

export default router

 我們路由的定義是很普遍的。對(duì)于需要權(quán)限驗(yàn)證的路由,我們需要增加額外的數(shù)據(jù),確保當(dāng)用戶訪問(wèn)它時(shí),我們可以識(shí)別它。這是添加到路由定義中的元屬性的本質(zhì)。如果你想問(wèn)_”我可以添加更過(guò)的數(shù)據(jù)給元數(shù)據(jù)并使用它嗎?”,我很堅(jiān)定的告訴你,這是絕對(duì)的😁。

解決未授權(quán)訪問(wèn)示例

我們有自己的路由定義?,F(xiàn)在,讓我們檢驗(yàn)未授權(quán)訪問(wèn)并采取行動(dòng)。在 router.js文件中,添加下面的在 export default router之前:

router.beforeEach((to, from, next) => {
 if(to.matched.some(record => record.meta.requiresAuth)) {
 if (store.getters.isLoggedIn) {
  next()
  return
 }
 next('/login') 
 } else {
 next() 
 }
})

從這篇文章,通過(guò)使用vue router來(lái)進(jìn)行身份驗(yàn)證,你可以回想一下我們這里有一個(gè)非常復(fù)雜的機(jī)制,它變得非常大,變得非?;靵y。vuex已經(jīng)幫我們簡(jiǎn)化了它,我們可以繼續(xù)給路由添加任何條件。在我們的vuex存儲(chǔ)中,我們可以定義操作來(lái)檢查這些條件并獲取返回它們的值。

解決Token過(guò)期示例

因?yàn)槲覀冊(cè)诒镜卮鎯?chǔ)token,它可以一直保留著。這意味著無(wú)論何時(shí),我們打開(kāi)自己的應(yīng)用,它可以自動(dòng)的驗(yàn)證用戶,即使token已經(jīng)過(guò)期失效。最多的情況是,我們的請(qǐng)求會(huì)因?yàn)闊o(wú)效token而持續(xù)失敗。這對(duì)于用戶是個(gè)不好的體驗(yàn)。

現(xiàn)在, 打開(kāi)./src/App.vue 文件并在script里面,添加下面的:

export default {
 [...]
 created: function () {
 this.$http.interceptors.response.use(undefined, function (err) {
  return new Promise(function (resolve, reject) {
  if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
   this.$store.dispatch(logout)
  }
  throw err;
  });
 });
 }
}

我們截獲axios請(qǐng)求,已確定是否獲取到401未授權(quán)響應(yīng)。如果這么做,我們分發(fā) logout 事件,那么用戶獲得退出應(yīng)用。這會(huì)讓用戶跳轉(zhuǎn)到之前設(shè)計(jì)的 login頁(yè)面,這樣他們可以再次登錄。

我贊同這樣會(huì)提升用戶體驗(yàn) ☺️.

結(jié)束

從以前的文章來(lái)看,您可以看到,基于vuex的引入,我們目前的應(yīng)用程序發(fā)生了重大變化?,F(xiàn)在,我們不依賴于一直檢查token,不管到哪里都有混亂的條件。我們可以簡(jiǎn)單地使用vuex存儲(chǔ)來(lái)管理權(quán)限,并且只需使用幾行代碼檢查應(yīng)用程序中的狀態(tài)。

以上所述是小編給大家介紹的使用Vuex解決Vue中的身份驗(yàn)證問(wèn)題,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!

網(wǎng)站標(biāo)題:使用Vuex解決Vue中的身份驗(yàn)證問(wèn)題
網(wǎng)站鏈接:http://muchs.cn/article12/gpjhdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、Google品牌網(wǎng)站制作、網(wǎng)站策劃、網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化