vue項目中存儲與使用后端傳遞過來的token
前言
以前一直都是在postman中測試驗證token,現(xiàn)在用在真正的項目中,記錄一下在vue項目中token的存儲和使用
后端關(guān)于token的設(shè)置
app.js中需要設(shè)置token的地方
const expressJWT = require('express-jwt')
const app = express();
const config = require('./config')
app.use(expressJWT({secret: config.jwtSecretKey}).unless({path: [/^\/api\/users/]}))
const testRouter = require('./routes/testToken')
app.use('/my', testRouter)
config中就是一個秘鑰,我單獨寫了一個文件,不再放上來了
unless后面是不需要token的地址,也就是以/api/users開頭的鏈接都不需要token驗證
用到的testToken.js如下:
const express = require('express');
const router = express.Router();
const test = require('../router_handler/testToken')
router.get('/current', test.test)
module.exports = router
使用模塊化的寫法,真正的路由處理函數(shù)寫在/router_handler/testToken.js中,內(nèi)容如下:
const db = require('../db/index');
exports.test = (req, res) => {
const sql = 'select * from users where id = ?'
db.query(sql, req.user.id, (err, results) => {
if(err) return res.send({status: 404, message: err})
if(results.length !== 1) return res.send({status: 404, messsage: '獲取用戶信息失敗,需重新登錄'})
res.json(results[0])
})
// res.send(req)
}
實際上就是一個獲取用戶信息的處理函數(shù),在mysql中根據(jù)id查詢用戶信息
注意,重點來了,經(jīng)過上述一系列設(shè)置后,當(dāng)我們訪問非/api/users開頭的鏈接的時候,都需要驗證,也就是在請求參數(shù)中提供token,而這個token則是在登錄的時候給出的,我寫在用戶登錄的處理函數(shù)中user.js,如下
// 用戶登錄的處理函數(shù)
exports.login = (req, res) => {
const userinfo = req.body
const sql = 'select * from users where name = ?'
db.query(sql, userinfo.name, (err, results) => {
if(err) return res.send({status: 404, message: err.message})
if(results.length !== 1) return res.status(404).json('用戶不存在!')
const compareResults = bcrypt.compareSync(userinfo.password, results[0].password)
if(!compareResults) return res.status(404).json('密碼錯誤!')
const user = {
id: results[0].id,
name: results[0].name,
avatar: results[0].avatar,
identify: results[0].identify
}
const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: '10h'})
res.json({
status:200,
message: '登錄成功',
// result: results[0],
token: 'Bearer ' + tokenStr
})
})
}
不相關(guān)的代碼我就不寫了,注意看到tokenStr這個變量,就是存儲的token值,通過res響應(yīng)出來。
總結(jié)一下,后端存儲token的流程:
- 編寫登錄函數(shù),向頁面響應(yīng)token字符串;
- 入口文件中(app.js)設(shè)置需要提供token的路由,并提供解析token字符串的秘鑰;
- 編寫對應(yīng)的路由函數(shù),處理請求
至此,后端的關(guān)鍵要點已經(jīng)寫完了,進入前端token的存儲
前端頁面取用token
前端頁面在登錄的時候,應(yīng)該把后端響應(yīng)過來的token存儲起來,這樣就可以實現(xiàn)路由守護和免登陸的功能
token存儲
通過ajax請求路由地址,并訪問res.data中的token字符串,并存儲在瀏覽器中,步驟和寫法是固定的
我寫在Login.vue中,如下:
methods: {
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
this.$axios
.post("/users/login", this.loginUser)
.then(res => {
// console.log(res)
//token
const { token } = res.data
localStorage.setItem("eleToken", token)
this.$router.push("/index");
});
} else {
console.log("error submit!!");
return false;
}
});
}
}
const { token } = res.data通過解構(gòu)賦值的方式取出響應(yīng)數(shù)據(jù)中的token
localStorage.setItem("eleToken", token)將token存儲在瀏覽器本地

前端使用token實現(xiàn)路由守衛(wèi)
其實在后端代碼中寫的unless就是路由守衛(wèi)的意思,不過前端應(yīng)該也要有這個,不然不用登錄就可以訪問到網(wǎng)站的內(nèi)容了,這顯然不合理
看看前端怎么寫的,寫在router.js中
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from './views/Index.vue'
import Register from './views/Register.vue'
import NotFound from './views/404.vue'
import Login from './views/Login.vue'
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{ path: '*', name: '/404', component: NotFound },
{ path: '/', redirect: '/index' },
{ path: '/register', name: 'register', component: Register },
{ path: '/index', name: 'index', component: Index },
{ path: '/login', name: 'login', component: Login },
]
})
// 路由守衛(wèi)
router.beforeEach((to, from, next) => {
const isLogin = localStorage.eleToken ? true: false
if(to.path == '/login' || to.path == '/register'){
next()
}else {
isLogin ? next() : next('/login')
}
})
export default router
看路由守衛(wèi)后面的代碼就可以了
使用的是router中的beforeEach函數(shù)
使用的邏輯如下:
- 定義一個isLogin(布爾值),如果瀏覽器中l(wèi)ocalStorage中存有eleToken對象,則值為true,否則為false
- 確定哪些路由不需要攔截:to.path == '/login' || to.path == '/register'也就是登錄和注冊不需要攔截,直接放行,用next()
- 對于攔截的路由,判斷isLogin是否為true,是就說明已經(jīng)登錄過了,有token,直接放行,如果為false,就跳轉(zhuǎn)到登錄的路由。
請求攔截和響應(yīng)攔截
還有一點沒有搞定,需要判斷當(dāng)前的token是不是過期了的,因為后端寫token的時候是給了個10小時的有效期,過期后,應(yīng)該重新登錄才對
這里我寫在一個單獨的http.js文件中,先上代碼
import axios from "axios";
import { Message, Loading } from 'element-ui';
import router from "./router"
let loading;
function startLoading(){
loading = Loading.service({
lock: true,
text: '數(shù)據(jù)加載中',
background: 'rgba(0,0,0,0.7)'
})
}
function endLoading(){
loading.close();
}
// 請求攔截
axios.interceptors.request.use(config => {
startLoading();
if(localStorage.eleToken){
// 設(shè)置統(tǒng)一的請求頭
config.headers.Authorization = localStorage.eleToken
}
return config
}, error => {
return Promise.reject(error)
})
//響應(yīng)攔截
axios.interceptors.response.use(response => {
endLoading();
return response
}, error => {
// 錯誤提醒
endLoading();
Message.error(error.response.data)
// 獲取錯誤狀態(tài)碼
const {status} = error.response
if(status == 401){
Message.error("token失效,請重新登錄")
localStorage.removeItem('eleToken')
router.push('/login')
}
return Promise.reject(error)
})
export default axios
看后面的請求攔截和響應(yīng)攔截就可以了
分兩步:
請求攔截,當(dāng)請求數(shù)據(jù)的時候,判斷l(xiāng)ocalStorage中是否存儲了eleToken,有的話,就把它寫到請求頭中去響應(yīng)攔截,當(dāng)token過期后,頁面會響應(yīng)一個401的錯誤狀態(tài)碼,這里要做的事情就是要把這個過期的token清除,并跳轉(zhuǎn)到登錄頁面
注意,這里坑的一筆,坑了博主一個下午,我寫的
頁面會響應(yīng)一個401的錯誤狀態(tài)碼
對嗎,但是經(jīng)過測試,token過期后根本就沒有跳轉(zhuǎn)到登錄頁面啊,后來我打印了一下這個status,發(fā)現(xiàn)這個值等于0啊,坑爹呢不是嗎,所以響應(yīng)攔截這里正確的寫法應(yīng)該是:
//響應(yīng)攔截
axios.interceptors.response.use(response => {
endLoading();
return response
}, error => {
// 錯誤提醒
endLoading();
Message.error(error.response.data)
console.log(error.response)
// 獲取錯誤狀態(tài)碼
const {status} = error.response
console.log(status)
if(status === 0){
Message.error("token失效,請重新登錄")
localStorage.removeItem('eleToken')
// console.log(error)
router.push('/login')
}
return Promise.reject(error)
})
把狀態(tài)碼改過來后就正常跳轉(zhuǎn)了。
至此,前后端token的使用都已經(jīng)順暢了~~
總結(jié)
到此這篇關(guān)于vue項目中存儲與使用后端傳遞過來的token的文章就介紹到這了,更多相關(guān)vue存儲使用后端傳遞的token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解三種方式解決vue中v-html元素中標(biāo)簽樣式
這篇文章主要介紹了三種方式解決vue中v-html元素中標(biāo)簽樣式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
Vue中為什么要引入render函數(shù)的實現(xiàn)
本文主要介紹了Vue中為什么要引入render函數(shù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01
vue.extend,mixins和vue.component的區(qū)別及說明
Vue.extend 創(chuàng)建Vue的子類,可視為組件構(gòu)造函數(shù),Vue.mixin 允許全局添加方法或?qū)傩?方便所有組件使用,Vue.component 是插件注冊方法,通過Vue.extend創(chuàng)建的組件實例可以注冊到Vue全局,使其在任何組件中可用2024-09-09

