您好,登錄后才能下訂單哦!
這篇“vue項目中怎么存儲與使用后端傳遞過來的token”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“vue項目中怎么存儲與使用后端傳遞過來的token”文章吧。
app.js中需要設置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中,內容如下:
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)過上述一系列設置后,當我們訪問非/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 }) }) }
不相關的代碼我就不寫了,注意看到tokenStr這個變量,就是存儲的token值,通過res響應出來。
總結一下,后端存儲token的流程:
編寫登錄函數(shù),向頁面響應token字符串;
入口文件中(app.js)設置需要提供token的路由,并提供解析token字符串的秘鑰;
編寫對應的路由函數(shù),處理請求
至此,后端的關鍵要點已經(jīng)寫完了,進入前端token的存儲
前端頁面在登錄的時候,應該把后端響應過來的token存儲起來,這樣就可以實現(xiàn)路由守護和免登陸的功能
通過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
通過解構賦值的方式取出響應數(shù)據(jù)中的token
localStorage.setItem("eleToken", token)
將token存儲在瀏覽器本地
其實在后端代碼中寫的unless就是路由守衛(wèi)的意思,不過前端應該也要有這個,不然不用登錄就可以訪問到網(wǎng)站的內容了,這顯然不合理
看看前端怎么寫的,寫在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,就跳轉到登錄的路由。
還有一點沒有搞定,需要判斷當前的token是不是過期了的,因為后端寫token的時候是給了個10小時的有效期,過期后,應該重新登錄才對
這里我寫在一個單獨的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){ // 設置統(tǒng)一的請求頭 config.headers.Authorization = localStorage.eleToken } return config }, error => { return Promise.reject(error) }) //響應攔截 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
看后面的請求攔截和響應攔截就可以了
分兩步:
請求攔截,當請求數(shù)據(jù)的時候,判斷l(xiāng)ocalStorage中是否存儲了eleToken,有的話,就把它寫到請求頭中去響應攔截,當token過期后,頁面會響應一個401的錯誤狀態(tài)碼,這里要做的事情就是要把這個過期的token清除,并跳轉到登錄頁面
注意,這里坑的一筆,坑了博主一個下午,我寫的
頁面會響應一個401的錯誤狀態(tài)碼
對嗎,但是經(jīng)過測試,token過期后根本就沒有跳轉到登錄頁面啊,后來我打印了一下這個status,發(fā)現(xiàn)這個值等于0啊,坑爹呢不是嗎,所以響應攔截這里正確的寫法應該是:
//響應攔截 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)碼改過來后就正常跳轉了。
以上就是關于“vue項目中怎么存儲與使用后端傳遞過來的token”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。