手把手带你入门Koa+sequelized完成注册登录+TodoList功能 day3

181 阅读4分钟
  1. 拆分中间件

新建src/middleware/user/middleware.user.js

const {getUserInfo} = require("../service/user.service")
const userValidator = async (ctx,next)=>{
    const { user_name,password} = ctx.request.body
     //合法性
     if(!user_name||!password){
        console.error('用户名或密码为空',ctx.request.body);
        ctx.body = {
            code: "10001",
            message: " 用户名或密码为空",
            result: "",
        }
        return
      }
      await next()

}
const verifyUser = async (ctx,next)=>{
    const {user_name} = ctx.request.body
      //合理性
      if(await getUserInfo({user_name})){
        ctx.body = {
            code: "10002",
            message: "用户已经存在",
            result: "",
        }
        return
       }
       await next()
}
module.exports = {
    userValidator,
    verifyUser
}

user.route.js中

const Router = require('koa-router')

const router = new Router({prefix: '/users'})
const {userValidator,verifyUser} = require('../middleware/user.middleware')

const {register} = require('../controller/user.controller')

const {login} = require('../controller/user.controller')

//注册接口
router.post('/register',userValidator,verifyUser,register)
//登录接口
router.post('/login',login)

module.exports = router

user.controller.js

const { createUser, getUserInfo } = require("../service/user.service");

class UserController {
  async register(ctx, next) {
    // 1. 获取数据
    // console.log(ctx.request.body)
    const { user_name, password } = ctx.request.body;
    try {
       // 2. 操作数据库
      const res = await createUser(user_name, password);
      // console.log(res)
      // 3. 返回结果
      ctx.body = {
        code: 0,
        message: "用户注册成功",
        result: {
          id: res.id,
          user_name: res.user_name,
        },
      };
    } catch (err) {
      console.log(err);
      ctx.status = 500
      ctx.body = {
        code: "10003",
        message: "用户注册错误",
        result: "",
      };
    }
  }
  async login(ctx, next) {
    ctx.body = "用户登录成功";
  }
}

module.exports = new UserController();
  1. 加密

在密码保存到数据库之前,要对密码进行加密处理

安装bcryptjs

npm install bcryptjs

编写中间件

user.middleware.js

const bcrypt = require('bcryptjs')

const {getUserInfo} = require("../service/user.service")

const userValidator = async (ctx,next)=>{
    const { user_name,password} = ctx.request.body
     //合法性
     if(!user_name||!password){
        console.error('用户名或密码为空',ctx.request.body);
        ctx.status = 400
        ctx.body = {
            code: "10001",
            message: " 用户名或密码为空",
            result: "",
        }
        return
      }
      await next()

}
const verifyUser = async (ctx,next)=>{
    const {user_name} = ctx.request.body
      //合理性
      ctx.status = 409
      if(await getUserInfo({user_name})){
        ctx.body = {
            code: "10002",
            message: "用户已经存在",
            result: "",
        }
        return
       }
       await next()
}
const cryptPassword =async (ctx,next)=>{
    const {password} = ctx.request.body

    const salt = bcrypt.genSaltSync(10);
    //hash保存的是密文
    const hash = bcrypt.hashSync(password,salt)

    ctx.request.body.password = hash

    await next()
}
module.exports = {
    userValidator,
    verifyUser,
    cryptPassword
}

挂载路由

user.route.js

const Router = require('koa-router')

const router = new Router({prefix: '/users'})
const {userValidator,verifyUser,cryptPassword} = require('../middleware/user.middleware')

const {register} = require('../controller/user.controller')

const {login} = require('../controller/user.controller')

//注册接口
router.post('/register',userValidator,verifyUser,cryptPassword,register)
//登录接口
router.post('/login',login)

module.exports = router
  1. 登录认证

user.middle.js

新增verifyLogin方法验证登录

const bcrypt = require('bcryptjs')

const {getUserInfo} = require("../service/user.service")

const userValidator = async (ctx,next)=>{
    const { user_name,password} = ctx.request.body
     //合法性
     if(!user_name||!password){
        console.error('用户名或密码为空',ctx.request.body);
        ctx.status = 400
        ctx.body = {
            code: "10001",
            message: " 用户名或密码为空",
            result: "",
        }
        return
      }
      await next()

}
const verifyUser = async (ctx,next)=>{
    const {user_name} = ctx.request.body
      //合理性
      ctx.status = 409
      if(await getUserInfo({user_name})){
        ctx.body = {
            code: "10002",
            message: "用户已经存在",
            result: "",
        }
        return
       }
       await next()
}
const cryptPassword =async (ctx,next)=>{
    const {password} = ctx.request.body

    const salt = bcrypt.genSaltSync(10);
    //hash保存的是密文
    const hash = bcrypt.hashSync(password,salt)

    ctx.request.body.password = hash

    await next()
}

const verifyLogin = async (ctx,next)=>{
    //判断用户是否存在(不存在报错)
    const {user_name,password} = ctx.request.body
    try {
        const res = await getUserInfo({user_name})
        if(!res){
            console.error('用户名不存在',{user_name});
            ctx.status = 409
            ctx.body = {
                code: "10004",
                message: "用户不存在",
                result: "",
            }
            return
        }
        if(!bcrypt.compareSync(password,res.password)){
            ctx.status = 500
            ctx.body = {
                code: "10006",
                message: "密码错误",
                result: "",
            }
            return
        }
    }catch(err){
        console.error(err);
        ctx.status = 500
        ctx.body = {
            code: "10005",
            message: "用户登录失败",
            result: "",
        }
        return
    }
    
    //密码是否匹配(不匹配报错)

}
module.exports = {
    userValidator,
    verifyUser,
    cryptPassword,
    verifyLogin
}

在user.route.js中挂载

router.post('/login',userValidator,verifyLogin,login)
  1. 用户的认证

登录成功,给用户颁发一个token,之后用户在每一次的请求中都带token

  • jwt:JSON web token
    • header:头部
    • playload:载荷
    • signature:签名

安装

npm install jsonwebtoken

user.controller.js

const { createUser, getUserInfo } = require("../service/user.service");
const jwt = require('jsonwebtoken');
const {JWT_SECRET} = require('../config/config.default')
class UserController {
  async register(ctx, next) {
    // 1. 获取数据
    // console.log(ctx.request.body)
    const { user_name, password } = ctx.request.body;
    try {
       // 2. 操作数据库
      const res = await createUser(user_name, password);
      // console.log(res)
      // 3. 返回结果
      ctx.body = {
        code: 0,
        message: "用户注册成功",
        result: {
          id: res.id,
          user_name: res.user_name,
        },
      };
    } catch (err) {
      console.log(err);
      ctx.status = 500
      ctx.body = {
        code: "10003",
        message: "用户注册错误",
        result: "",
      };
    }
  }
  async login(ctx, next) {
    const {user_name} = ctx.request.body
    //获取用户信息(token的payload中要记录id,user_name,is_admin)
    try {
      // 从返回对象结果中剔除password属性,其他属性放在res对象
      const {password,...res} = await getUserInfo({user_name})
      ctx.body = {
        code: 0,
        message:'用户登录成功',
        result:{
          token: jwt.sign(res,JWT_SECRET,{expiresIn:'1d'})
        }
      } 
    }catch(err){
      console.error('用户登录失败');
    }
  }
}

module.exports = new UserController();

.env

JWT_SECRET = xzd
  1. 修改密码

分为两个步骤,先将密码加密,之后操作数据库Update

user.route.js

const Router = require('koa-router')

const router = new Router({prefix: '/users'})
const {userValidator,verifyUser,cryptPassword,verifyLogin} = require('../middleware/user.middleware')

const {register} = require('../controller/user.controller')

const {login} = require('../controller/user.controller')

const {changePassword} = require('../controller/user.controller')

const {auth} = require('../middleware/auth.middleware')

//注册接口
router.post('/register',userValidator,verifyUser,cryptPassword,register)
//登录接口
router.post('/login',userValidator,verifyLogin,login)
//修改密码
router.patch('/',auth,cryptPassword,changePassword)

module.exports = router

user.controller.js

const { createUser, getUserInfo,updateById } = require("../service/user.service");
const jwt = require('jsonwebtoken');
const {JWT_SECRET} = require('../config/config.default')
class UserController {
  async register(ctx, next) {
    // 1. 获取数据
    // console.log(ctx.request.body)
    const { user_name, password } = ctx.request.body;
    try {
       // 2. 操作数据库
      const res = await createUser(user_name, password);
      // console.log(res)
      // 3. 返回结果
      ctx.body = {
        code: 0,
        message: "用户注册成功",
        result: {
          id: res.id,
          user_name: res.user_name,
        },
      };
    } catch (err) {
      console.log(err);
      ctx.status = 500
      ctx.body = {
        code: "10003",
        message: "用户注册错误",
        result: "",
      };
    }
  }
  async login(ctx, next) {
    const {user_name} = ctx.request.body
    //获取用户信息(token的payload中要记录id,user_name,is_admin)
    try {
      // 从返回对象结果中剔除password属性,其他属性放在res对象
      const {password,...res} = await getUserInfo({user_name})
      ctx.body = {
        code: 0,
        message:'用户登录成功',
        result:{
          token: jwt.sign(res,JWT_SECRET,{expiresIn:'1d'})
        }
      } 
    }catch(err){
      console.error('用户登录失败');
    }
  }
  async changePassword(ctx,next){
    const id = ctx.state.user.id
    const password = ctx.request.body.password
    console.log(id,password);
    const res = await updateById({id,password})
    if(res>0){
      ctx.body = {
        code: '0',
        message: '修改密码成功',
        result: ''
      }
    }else {
      ctx.body = {
        code: '10007',
        message: '修改密码失败',
        result: ''
      }
    }
  }
}

module.exports = new UserController();

user.service.js

const User = require("../model/user.model");
class UserService {
  async createUser(user_name, password) {
    //todo:写入数据库
    const res = await User.create({
      //表的字段
      user_name,
      password,
    });
    console.log(res);
    return res.dataValues;
  }
  async getUserInfo({id,user_name,password,is_admin}){
    const whereOpt = {}
    id && Object.assign(whereOpt,{id})
    user_name && Object.assign(whereOpt,{user_name})
    password && Object.assign(whereOpt,{password})
    is_admin && Object.assign(whereOpt,{is_admin})

    const res =  await User.findOne({
      attributes:['id','user_name','password','is_admin'],
      where:whereOpt
    })

    return res?res.dataValues:null
  }
  async updateById({id,user_name,password,is_admin}) {
    console.log(id,user_name,password,is_admin);
    const whereOpt = {id}
    const newUser = {}
    password && Object.assign(newUser,{password})
    user_name && Object.assign(newUser,{user_name})
    is_admin && Object.assign(newUser,{is_admin})
    const res = await User.update(newUser,{where:whereOpt})
    console.log(newUser);
    console.log(res);
    return res[0] > 0?true:false
  }
}
module.exports = new UserService();

这样就是一个最基础的Koa实现注册登录的项目啦!