• 【koa2】用户注册、登录校验与加盐加密


    加密与解密

     先介绍一下关于服务端用户名跟密码的存储状态,我们知道当前端在注册一个新用户时,会在表单内填入用户名和密码,并通过post请求提交到服务器,服务器再把用户名和密码从ctx.request.body中拿出来,存入到数据库的一张表里。这张表通常会被命名为users。

      关键在于,服务器如何存入用户名和密码到数据库。直接存?不可能的,这样太不安全了,永远不要在一张表中出现全部用户名和密码一览无余的危险情况。

      所以比较好的处理方法是这样的,服务器先对用户的密码进行加盐加密,再存到数据库。

      那密码验证呢?则是接收前端输入的明文密码,与数据库中相应的加密密码进行比对,如果正确,则表示登录成功。注意:如果有人拿到这个加密的密码,也是没用的。因为比对正误的方法已经在服务器写死,只能是比对明文密码与加密密码是否吻合。如果接收到两个一模一样的加密密码,验证也不会通过。

      至于如何比对明文密码与加密密码,不用担心,加密解密的方法都是一起配对生产的。bcryptjs就是这样一款不错的加解密工具。(因为在windows上安装bcrypt会报错,据说其他系统没问题,所以改为安装bcryptjs,其api和使用方法与bcrypt完全一样)

      我在一个js模块中定义了两个方法,一个加密,一个解密。在加密算法中,首先我们需要生成盐,所谓盐,就是先在明文密码中混入一些无规则的字符。传入的数字越大,代表混入的盐越复杂。最后通过hashSync方法生成加密密码并返回。而解密方法就更加简单,直接调用封装的compareSync方法进行明文密码与加密密码比对。

      

    用户注册

      在服务端路由模块,暴露一个register接口,用于接收前端注册信息,对密码进行加盐加密,并存入数据库的操作。

    const router = require("koa-router")();
    const UserModel = require("../schema/user");
    const Crypt = require("./crypt");
    const jwt = require("jsonwebtoken");
    
    // 新增一名用户
    router.post("/register", async ctx => {
      const UserEntity = new UserModel(ctx.request.body);
      UserEntity.password = Crypt.encrypt(UserEntity.password);
      await UserEntity.save()
        .then(() => {
          ctx.body = {
            code: 200,
            msg: "register successfuly"
          };
        })
        .catch(() => {
          ctx.body = {
            code: 500,
            msg: "register failed"
          };
        });
    });

    (看一下我这段代码,有几个需要说明的地方:第一,我是通过userModel这一个模型的save方法将这条数据存入mongoDB数据库中,至于model、schema的概念问题,先不在这里赘述;第二:存储失败的原因可能是网络问题,服务端程序出错,但最大的可能还是因为我在userSchema里定义了用户名的不可重复性,也就是所谓的“该用户名已存在”)。

      为了阐述方便,这里将userModel的定义代码贴出来:

      

    登录校验

      让我们回到服务端路由模块,看下怎样去完成一个登录校验。

      

    // 登录校验
    router.post("/login", async ctx => {
      const data = ctx.request.body;
      await UserModel.findOne({ account: data.account })
        .then(res => {
          const checkPassword = Crypt.decrypt(data.password, res.password);
          if (checkPassword) {
            const token = jwt.sign({ account: res.account }, "zhangnan", {
              expiresIn: "2h"
            });
            ctx.body = { code: 200, msg: "successfuly login", token: token };
          } else {
            ctx.body = { code: 500, msg: "wrong password" };
          }
        })
        .catch(() => {
          ctx.body = { code: 501, msg: "user does not exist" };
        });
    });

      首先,我们根据用户输入的用户名去数据库查找用户信息,如果查不到,说明用户名不存在,这是第一层逻辑。

      如果查到了,则调用刚刚定义好的解密方法进行明文密码与加密密码比对,如错误,则告诉前端密码错误;如正确,则调用jwt的sign方法签发一个token给前端。签发的内容是用户名;后面前端再发来请求并携带这个token时,如果验证到token有效,那解析出来的用户名就是服务器判断前端请求身份的标识,它告诉服务器“我是xxx,且我处于已登录状态”。这是第二层逻辑。

      

  • 相关阅读:
    eclipse(java windows)
    Tomcat(Linux)
    Tomcat(Windows)
    MySql(Windows)
    Java EE API
    计算机网络-TCP三次握手理解
    onclick 和click 的区别
    js轮播图代码
    JS轮播图制作
    js动画原理
  • 原文地址:https://www.cnblogs.com/zhangnan35/p/11217978.html
Copyright © 2020-2023  润新知