tips: node+mysql
创建用户
model.ts: 定义用户的类
1 2 3 4 5
| export class UserModel{ id?:number; name?:string; password?:string }
|
service.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import {connection} from '../app/database/mysql'; import {UserModel} from './user.model';
/** * 创建用户 */ export const createUser = async (user:UserModel)=>{ //准备查询 const statement=` INSERT INTO user SET ? `;
//执行查询 const [data] = await connection.promise().query(statement,user);
//提供数据 return data; }
|
controller.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import {Request,Response,NextFunction} from 'express'; import {UserModel} from './user.model'; import * as userService from './user.service';
export const store = async ( request:Request, response:Response, next:NextFunction )=>{ //准备数据 const {name,password} = request.body;
//创建用户 try { const data = await userService.createUser({name,password}); response.status(201).send(data); } catch (error) { next(error) } }
|
router.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import express from 'express'; import * as userController from './user.controller';
const router = express.Router();
/** * 创建用户 */ router.post('/users',userController.store);
/** * 导出路由 */ export default router;
|
验证用户数据
middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import {Request,Response,NextFunction, request, response} from 'express'; import * as userService from './user.service';
/** * 验证用户数据 */ export const validateUserData = async ( request:Request, response:Response, next:NextFunction )=>{ console.log('验证用户数据');
//准备数据 const {name,password} = request.body;
//验证必填数据 if(!name) return next(new Error('NAME_IS_REQUIRED')); if(!password) return next(new Error('PASSWORD_IS_REQUIRED'));
//下一步 next(); }
|
router 使用的时候:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import express from 'express'; import * as userController from './user.controller'; import {validateUserData} from './user.middleware';
const router = express.Router();
/** * 创建用户 */ router.post('/users',validateUserData,userController.store);
/** * 导出路由 */ export default router;
|
处理创建用户的错误
在 app.middleware.ts 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { Request, Response, NextFunction } from 'express';
/** * 默认异常处理器 */ export const defaultErrorHandler = ( error: any, request: Request, response: Response, next: NextFunction, ) => { if(error.message){ console.log(error.message) } let statusCode: number, message: string;
/** * 处理异常 */ switch (error.message) { case 'NAME_IS_REQUIRED': statusCode = 400; message = '请提供用户名'; break; case 'PASSWORD_IS_REQUIRED': statusCode = 400; message = '请提供用户密码'; break; default: statusCode = 500; message = '服务暂时出了点问题~'; break; } response.status(statusCode).send({ message }); };
|
定义按用户名查找用户的服务
user.service.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| /** * 按用户名查找用户 */ export const getUserByName = async (name:string)=>{ //准备查询 const statement = ` SELECT id, name FROM user WHERE name = ? `
//执行查询 const [data] = await connection.promise().query(statement,name);
//提供数据 return data[0]; }
|
注册时检查用户名是否存在
user.middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import {Request,Response,NextFunction, request, response} from 'express'; import * as userService from './user.service';
/** * 验证用户数据 */ export const validateUserData = async ( request:Request, response:Response, next:NextFunction )=>{ console.log('验证用户数据');
//准备数据 const {name,password} = request.body;
//验证必填数据 if(!name) return next(new Error('NAME_IS_REQUIRED')); if(!password) return next(new Error('PASSWORD_IS_REQUIRED'));
//验证用户名 const user = await userService.getUserByName(name); if(user) return next(new Error('USER_ALREADY_EXIST'));
//下一步 next(); }
|
app.middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import { Request, Response, NextFunction } from 'express';
/** * 默认异常处理器 */ export const defaultErrorHandler = ( error: any, request: Request, response: Response, next: NextFunction, ) => { if(error.message){ console.log(error.message) } let statusCode: number, message: string;
/** * 处理异常 */ switch (error.message) { case 'NAME_IS_REQUIRED': statusCode = 400; message = '请提供用户名'; break; case 'PASSWORD_IS_REQUIRED': statusCode = 400; message = '请提供用户密码'; break; case 'USER_ALREADY_EXIST': statusCode = 409; message = '用户名已被占用'; break; default: statusCode = 500; message = '服务暂时出了点问题~'; break; } response.status(statusCode).send({ message }); };
|
存储密码
在数据仓库里直接存储用户设置的密码,会有很严重的安全问题,一般会用 hash 来处理密码数据,bcrypt 就是其中的一种 hash 方法,为了让密码更难猜到,在 hash 的时候会加点盐,盐就是随机的一串字符,把加了盐的字符再用 hash 方法处理下,这样就很难猜到了。在数据仓库中存储的是经过 hash 处理后的密码,顺便还要存储下盐。
hash 用户密码(bcrypt)
在 node 生态中有一个 bcrypt 的包,它里面提供了用 bcrypt 这种方法 hash 数据,然后比对 hash 数据的方法。
安装:
使用了 typescript 后还需要安装一下类型定义:
1
| npm install @types/bcrypt --save-dev
|
user.middleware.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import bcrypt from 'bcrypt'; /** * HASH 密码 */ export const hashPassword = async ( request:Request, response:Response, next:NextFunction )=>{ // 准备数据 const {password} = request.body;
//HASH密码 request.body.password = await bcrypt.hash(password,10);
//下一步 next(); }
|
user.router.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import express from 'express'; import * as userController from './user.controller'; import {validateUserData,hashPassword} from './user.middleware';
const router = express.Router();
/** * 创建用户 */ router.post('/users',validateUserData,hashPassword,userController.store); //在这里添加中间件
/** * 导出路由 */ export default router;
|