首先在node项目中安装需要的jsonwebtoken包
npm i jsonwebtoken
在node端编写接口(使用了express框架)
var express = require('express');
var router = express.Router();
//导入用于生成JWT字符串的包
const jwt = require('jsonwebtoken');
//secret 密钥的本质: 一个字符串
const secretKey = 'uluy'
// 登录
router.post('/login', function (req, res) {
var info = req.body
// userSQL.find函数是我自己封装的数据库查询函数,在此不做解释
userSQL.find({ account: info.account }).then(e => {
let data = e;
if (data == '') {
res.send('账号不存在')
} else {
if (data[0].password == info.password) {
var userinfo = data[0];
// 数据库修改方法
// UserModel.updateOne(查询条件,修改的值,回调)
userSQL.update({ account: info.account }, { logindate: info.logindate, isLogin: true }).then(e => {
// 将用户数据包含在token中,之后可以通过解析token获得用户数据(一般不携带密码)
var newinfo = { username: userinfo.username, account: userinfo.account, date: userinfo.date, friends: userinfo.friends }
// 用户登陆成功后跳转到其它页面时,无须再次输入用户名及密码等了,所以此处理服务器会生成并发送给用户一个token
const token = jwt.sign(
newinfo, // 除了密码
secretKey,
{ expiresIn: '600s' } // 定义失效时间
)
res.send({ userinfo: newinfo, token })
})
} else {
res.send('密码错误')
}
}
})
});
// 验证token是否过期
router.post('/isExpire',function(req,res){
let token=req.headers.authorization
//全局验证token是否过期
jwt.verify(token, secretKey, (err, payload) => {
if (err){
console.log('token过期');
res.json({ message:'token过期' })
}else{
console.log('token认证成功');
res.json({ message:'认证成功', payload })
}
})
})
// 存在token时登录
router.post('/hasToken', function (req, res) {
let userinfo = jwt.decode(req.headers.authorization, secretKey)
res.send(userinfo)
});
module.exports = router;
在vue项目中封装请求函数
// 登录
export function userLogin(data) {
return request({
url:`/users/login`,
method:'POST',
data
})
}
// 存在token登录
export function hasToken(data){
return request({
url:`/users/hasToken`,
method:'POST',
data
})
}
// 检测token是否过期
export function isExpire(data){
return request({
url:`/users/isExpire`,
method:'POSt',
data
})
}
// 注册
export function register(data) {
return request({
url:`/users/register`,
method:'POST',
data
})
}
vue项目中提前封装好操作cookie的函数
//获取cookie、若不存在则返回null
export function getCookie(name) {
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg))
return (arr[2]);
else
return null;
}
//设置cookie,增加到vue实例方便全局调用 expiredays有效时间(天数,可不传)
export function setCookie(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
};
//删除cookie
export function delCookie(name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null)
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
};
登录逻辑
login() {
const that = this;
let date = new Date().toLocaleString();
userLogin({ account: this.account, password: this.password, logindate: date }).then(res => {
if (res.data == '请求错误') that.$notify("请求错误,请检查网络连接或稍后再试!");
else if (res.data == '账号不存在') that.$notify("账号不存在,请先注册再登录");
else if (res.data == '密码错误') that.$notify("密码错误,请重新输入密码");
else {
// 在cookie中存储token
if (getCookie('token') != null) {
delCookie('token')
setCookie('token', res.data.token)
} else {
setCookie('token', res.data.token)
}
that.$notify({ type: 'success', message: "登录成功" });
that.$store.commit('setUserInfo',res.data.userinfo);
setTimeout(() => {
that.$router.push('home');
}, 1500);
}
})
},
注册逻辑
signUp() {
if (this.username && this.account && this.password) {
let date = new Date().toLocaleString();
register({ username: this.username, account: this.account, password: this.password, logindate: date }).then(res => {
if (res.data == '账号已存在') this.$notify('账号已存在,请前往登录或者修改账号!')
else if (res.data == '请求错误') this.$notify('请求错误,请检查网络连接或稍后再试!')
else {
this.$notify({ type: 'success', message: '注册成功!' })
this.$router.push('login');
}
})
} else {
this.$notify('请输入完整信息!')
}
}
添加全局路由守卫,检测进行路由跳转时,除登录、注册页面外,其他页面的token是否存在或过期
// 全局路由守卫
router.beforeEach((to, from, next) => {
// 如果是跳转到登录和注册页面,不检验token
if (to.path == '/login' || to.path == '/register') {
next()
}else{
// 先检验是否存在token,这里token是存在cookie中
if (getCookie('token')) {
// 检验token是否过期
isExpire().then(res => {
if (res.data.message == 'token过期') {
console.log('token过期了');
next('/login')
} else {
console.log('token正常');
next()
}
})
} else {
console.log('token不存在');
next('/login')
}
}
})
其他
此外,还可以在请求拦截器中添加token验证,原理与上文相似,在此不做详细介绍。