作者:时光
个人网站 (timebk.cn) | 我的Github | 我的Gitee
前言:在Vue项目中,我们需要实现验证用户是否登录和token是否过期,网上的教程层出不穷,有的是Copy,有的是晦涩难懂,本文将以最通俗易懂的方式和具体代码呈现给您!
前端运用:vue2、vue-router、Axios
后端运用:Node.js、express-generator、jsonwebtoken(token生成)
数据库:MongoDB
当我们需要实现验证功能时,首先应该知道我们需要用到 vue-router的导航守卫
和 Axios的请求拦截器
,前者主要实现验证用户是否登录,而后者主要实现验证token是否过期。
通过封装好的Axios方法获取到后端返回的 token
并存入 localStorage
(后端生成token方法在 后端方面 里):
this.$network({
url: `adminLogin?account=${form.account}&password=${form.password}`,
}).then((res) => {
// 判断请求是否正常请自行发挥
if (res.code == 200) {// 如果正常
//将后端返回的token存入localStorage
localStorage.setItem("token", res.token);
}
})
注:这里我们使用的是 router.beforeEach
目的:通过导航守卫进行 本地是否登录判断
,判断当前页面 是否是登录注册页
(或其它需要排除的页面),如果 是
,则进行是否 已登录
验证;如果 不是
,则进行是否 未登录
验证:
// 注:这里我们使用的是 `router.beforeEach`
if (to.fullPath == '/login') {// 排除页面
if (localStorage.getItem('token') != null) {
console.log('您已登录,是否访问首页?');
}
} else if (localStorage.getItem('token') == null) {
// 如果访问的是其它路由页面而且token不存在,即为未登录
localStorage.clear();// 清除一次 localStorage
console.log('您未登录,是否访问登录页?');
return
}
目的:通过axios的请求拦截器 interceptors
进行 请求前
、 请求后
的事件。
首先需要在 请求前 interceptors.request
里将 token
放到 headers中的Authorization中
,以便 每次发起网络请求时携带
:
// 请求前 interceptors.request
config.headers.Authorization = localStorage.getItem("token");
然后在 请求后 interceptors.response
里进行token是否过期验证
注:这里需要后端配合返回是特定的标识,具体方法请看 后端方面,我这里是返回的 loginStatus
为 false
,
当然首先我们还是需要判断一下当前页面 是否是登录注册页
(或其它需要排除的页面),如果 不是
,则 验证token是否过期
// 请求后 interceptors.response
if (window.location.pathname != '/login') {// 排除页面
if (res.data.loginStatus == false) {// 如果token已过期
localStorage.clear();// 清除一次 localStorage
console.log('登录状态已失效,是否访问登录页?');
}
}
到目前为止,前端方面就基本结束了,当然类如已登录跳转首页、未登录和token过期后跳转登录页的交互请自行发挥!
这里我用的是 Node.js + express-generator + MongoDB + jsonwebtoken(token生成插件)实现。
let token = req.headers.authorization;
这是一个生成token的插件,官方文档:https://www.npmjs.com/package/jsonwebtoken
// 安装
npm i jsonwebtoken
// 安装好后进行导入
const jwt = require('jsonwebtoken'); // token生成
我们主要用它的两个方法:jwt.sign()
和 jwt.verify()
payload 传入参数,从请求中接收,对象形式
token 传入需要验证的token值,一般从Authorization中接收,字符串形式
secretOrPrivateKey 秘密或公钥,生成方法和验证方法这里应该一样
[options, callback] 选项和回调,sign()的options一般用expiresIn:callback(过期事件,单位为秒);verify()的options一般为err(token已过期),
// time 过期时间,单位为秒s
jwt.sign({account: account,password:password},'userLogin',{expiresIn :time});
jwt.verify(token, 'userLogin', (err, data) => {
if (err) {// 过期token
console.log('已过期');
} else {// 有效token
console.log('未过期');
}
})
// token验证,生成时和请求验证时的都可以调用!返回token状态,false为已过期
function tokenVerify(token) {
let status;
jwt.verify(token, 'userLogin', (err, data) => {
if (err) {// 过期token
status = false
} else {// 有效token
status = true
}
})
return status
}
// token生成,只用于登录时调用!通过调用token验证函数,判断token是否过期,若未过期,则返回true,前端token值不变;若过期,则重新生成,前端重新保存token
function tokenGenerate(token, account, password, time) {
let status = tokenVerify(token);
if (status) {// 若token未过期
token = true;
} else {// 若token已过期
token = jwt.sign({ account: account, password: password }, 'userLogin', { expiresIn: time });
}
return token
}
就这样,前后端合作实现了验证用户是否登录和token是否过期,预留发挥空间大,可根据需求增加交互和验证!