-
拆分中间件
新建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();
-
加密
在密码保存到数据库之前,要对密码进行加密处理
安装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
-
登录认证
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)
-
用户的认证
登录成功,给用户颁发一个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
-
修改密码
分为两个步骤,先将密码加密,之后操作数据库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实现注册登录的项目啦!