//blog/tags/about/friends

带邀请码注册登陆开发笔记

- code node.js vue web register login

GitHub: https://github.com/jsun969/PigeonServer

最近在写研究课项目飞鸽传书,其中的注册登陆被我搞了好久,用这篇文章记录一下
看下效果(前端样式用了Vuetify,吹爆Materical Design)

登录界面

登陆完了

后端

好像都是柯灰大佬推荐的

Mongoose

上次用了 mongodb 原生的包,不太爽,于是换成了 Mongoose

const mongoose = require('mongoose');

const userSchema = mongoose.Schema({
  username: String,
  password: String,
});

module.exports = mongoose.model('User', userSchema);

用户信息模板

router.post('/register', async (req, res) => {
  try {
    const doc = await User.findOne({ username: req.body.username });
    if (!doc) {
      const codeDoc = await InviteCode.findOneAndUpdate(
        { code: req.body.inviteCode },
        { username: req.body.username },
      );
      if (!codeDoc) {
        console.log(
          `User [ ${req.body.username} ] try to register, but the invite code is wrong.`,
        );
        res.status(404).json({ error: 'InviteCodeNotFound' });
      } else if (codeDoc.username) {
        console.log(
          `User [ ${req.body.username} ] try to register, but the invite code has been used.`,
        );
        res.status(404).json({ error: 'InviteCodeIsUsed' });
      } else {
        const user = new User({
          username: req.body.username,
          password: crypto
            .createHash('sha256')
            .update(req.body.password)
            .digest('hex'),
        });
        userRes = await user.save();
        console.log(`User [ ${userRes.username} ] register successfully!`);
        res.sendStatus(200);
      }
    } else {
      console.log(`User [ ${req.body.username} ] has already registered.`);
      res.status(404).json({ error: 'DuplicateUsername' });
    }
  } catch (error) {
    console.error(error);
    res.status(500).send({ error });
  }
});

注册(好像有些代码冗余)

JsonWebToken

代替 Session 做用户存储,不占我数据库 2333

router.post('/login', async (req, res) => {
  try {
    const doc = await User.findOne({
      username: req.body.username,
      password: crypto
        .createHash('sha256')
        .update(req.body.password)
        .digest('hex'),
    });
    if (doc !== null) {
      console.log(`User [ ${req.body.username} ] login successfully.`);
      const token = jwt.sign({ userId: doc._id }, cfg.token.secret, {
        expiresIn: cfg.token.maxAge,
      });
      res.json({ token });
    } else {
      console.log(`User [ ${req.body.username} ] login error.`);
      res.status(404).json({ error: 'LoginError' });
    }
  } catch (error) {
    console.error(error);
    res.status(500).send({ error });
  }
});

登陆成功即发送 Token

router.post('/token-verify', async (req, res) => {
  try {
    const decoded = jwt.verify(req.body.auth, cfg.token.secret);
    const { username } = await User.findById(decoded.userId);
    console.log(`User [ ${username} ] login with token successfully.`);
    res.json({ username });
  } catch (error) {
    console.error(error);
    res.status(500).send({ error });
  }
});

验证用户 Token

前端

没啥的其实,记录一点语法糖

解构赋值

峰神教的,针不戳

async function login() {
  if (this.isLoginBtnDisabled) return;
  try {
    const { loginName: username, loginPwd: password } = this;
    const userData = { username, password };
    const { status, data } =
      (await axios.post(`${this.$store.state.reqUrl}/user/login`, userData)) ||
      {};
    if (status === 200) {
      this.$emit('login-success', username);
      localStorage.setItem('userToken', data.token);
    }
  } catch ({
    response: {
      status,
      data: { error },
    },
  }) {
    if (status === 404) {
      this.$emit('login-error');
    } else if (status === 500) {
      this.$emit('server-error', error.code);
    }
  }
  this.loginName = '';
  this.loginPwd = '';
}

登陆请求

async…await

本来有点一知半解

async function created() {
  try {
    const {
      status,
      data: { username },
    } =
      (await axios.post(`${this.$store.state.reqUrl}/user/token-verify`, {
        auth: localStorage.getItem('userToken'),
      })) || {};
    this.isLogin = status === 200;
    this.loginUsername = username;
  } catch (error) {
    return;
  }
}

验证本地 Token