基于jsonwebtoken+vue路由守卫,在vue2+node项目中使用cookie+token实现登录、注册功能

首先在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验证,原理与上文相似,在此不做详细介绍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值