之前本来是想把学习用的nest测试项目部署上去实现增删改查已经联表查询功能试试的,但是想想既然已经部署到服务端并且能正常运行了,那本地跟服务端差别不大了,还不如搞个真正的需求部署上去,所以今天想自己用nuxt3+vue3+vant4+nestjs+mysql实现一个简单的人员管理系统
首先第一步:阿里云服务器实例转配
之前选了按量付费,一天要五块多,太心疼了,转包月先
正式开始:
1、新建nest项目
在我们想要新建nest项目的目录下打开命令行工具运行以下命令
nest new project-name
为了让我们的请求地址看起来正规一点,我们这里加上一个统一的前缀吧
main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('manager')
await app.listen(3000);
}
2、新建user模块
src目录下运行以下命令
nest g res user
出现选项选第一个跟Y就行了,它们自动把你新建的模块引入到app主模块中去
src目录下已经有user模块并且在app.module中自动引入了
3、启动nestjs项目
要加dev,才有热更新
npm run start:dev
报了个错:
因为这个端口之前有个工程正在用着,那我们先把这个工程关掉吧,暂时用不着,重新启动,出现以下这些表示成功了
访问一下:localhost:3000
找不到地址,因为我们之前设置了全局的前缀manager,加上
成功
我们先来构建一个用户的实体吧,一个用户拥有哪些基本数据:
用户名,不能重复,昵称(可选),密码,创建时间,最后一次登录时间,角色(用于控制权限,后面需要新建权限表),id(自增),用户状态(枚举值),deleted(用于软删除,新建时默认为否),token数组,因为考虑到多端登录情况,暂时想到这些,后面可以再加,其实还想搞个头像功能的,但是考虑到还要专门搞个文件服务器,还是先不搞了
过程:
1、新建user,token实体
2、在app.module中引入TypeOrmModule连接数据库
3、在user.module中引入TypeOrmModule并放入user,token实体
4、在user.service中引入两张库表,用来对对应表进行增删改查操作
都保存完之后数据库中已经出现这两张表了
新增用户接口写好之后调一下接口(中间具体过程不细讲,看完nestjs教程基本上就知道怎么搞了)
成功了,再看下数据库中数据,有了
为了后面删除操作,我们多搞了几条测试数据
自己把增删改查搞定了,中间过程省略,这里默认你们是会nest的,后续等我熟悉了nest可以考虑再仔细讲讲,现在自己也是个初学者状态
4、新建nuxt3前端工程
npx nuxi@latest init <project-name>
后面很多活都可以交给tongyilingma了,比如你直接跟他说,我要用某某组件(例:element-plus,甚至可以带上具体版本号)写一个后台管理页面,或者写一个表格,表格里面有哪些内容,写一个弹窗,弹窗里面有哪些内容,然后copy到页面里面,改写数据,就差不多了,看下效果
增删改查都写好了,增删改查的弹窗都可以交给tongyilingma然后自己稍微改改调接口就行
经测试增删改查功能都没问题,接着我们既然要模拟真实应用,就要对后端应用进行改良
5、登录
登录方法给用户发token,数组存储,但是我们这里暂时只允许存在一个token
jwt依赖自己安装:
npm i jsonwebtoken
const jwt = require('jsonwebtoken');
调用login方法,搞定
token校验,校验通过返回用户信息即可:
async checkToken(token: string) {
try {
const decoded = jwt.verify(token, secretKey);
console.log('checktoken decoded ', decoded.userId)
if (decoded.userId) { // 验证通过,返回用户信息
const user = await this.usersRespository.findOne({
where:
{ id: decoded.userId }
});
console.log('checktoken user ', user)
return user
}
return decoded;
} catch (err) {
console.log('checkToken err ', err)
return null;
}
}
6、密码加解密
- 前后端传输加密,这里用我们常用的aes(对称加解密),这一步搞了好久,篇幅较长,重起一片文章写这个了:前端cryptojs加解密,后端node环境(nestjs)crypto加解密
- 数据库存储密码加密,我们肯定不能直接前端加密密码传输然后后端直接将前端aes加密后的密码字段存在数据库,因为我们知道对称加密前后端秘钥一致,且这个秘钥是很容易搞到的,所以如果直接存前端传过来的加密密码方案肯定不可行,而且一般前后端加密传输一般都是针对整个请求对象加解密,一般不止针对密码加密
- 所以这里我们用nestjs推荐的bcypt
npm i bcrypt npm i -D @types/bcrypt
- 存储密码前加密
-
user.password = await bcrypt.hash(user.password, config.pwdSaltOrRounds)
调用添加方法,再查看数据库:
-
可以看到,数据已经被加密了
这时候我们能想到,之前登录方法里面的用户名密码对比肯定走不通了,bcrypt提供了对比方法,因为我们给user的实体中的password设置了select:false,是无法查询到的,所以这里要加select才能查出来
调用一下登录方法,成功
注意要在我们搞完加解密之后调接口新产生的数据,才是有做数据库存储加解密的数据
让我们输个错误密码试下,没问题
在这里说一下,不要用前端传入密码用bcrypt加密然后跟数据库存储的密码去做对比,因为每次机密产生的字符串都是不一样的,结果永远是false,要用bcrypt提供的同步对比方法
bcrypt.compareSync(password, res[0].password)
7、权限控制
这是最后一步,作为管理系统,用户的增删改查肯定不是所有用户都有权限操作,所以我们要加一个权限控制,所以我们要在加一个用户角色表
每个用户暂时只能有一个角色吧,一对一
每个路由前面加个权限判断
if (headers.token) {
const hasPermission = await this.userService.hasPermission(PermissionCode.ADD, headers.token)
if (hasPermission) {
return await this.userService.create(createUserDto);
} else {
return { message: '没有添加用户权限' };
}
} else {
return {
message: '没有添加用户权限'
}
}
权限判断
async hasPermission(permission: PermissionCode, token: string): Promise<boolean> {
if (!permission || !token) {
return false
}
const adminPermissions = [PermissionCode.ADD, PermissionCode.DELETE, PermissionCode.UPDATE, PermissionCode.QUERY]
const operatorPermissions = [PermissionCode.ADD, PermissionCode.QUERY]
const userPermissions = [PermissionCode.QUERY]
const user = await this.checkToken(token)
console.log('hasPermission user ', user)
if (user && user.roles && user.roles.code) {
if (user.roles.code === RoleCode.ADMIN && adminPermissions.includes(permission)) {
return true
}
if (user.roles.code === RoleCode.Operator && operatorPermissions.includes(permission)) {
return true
}
if (user.roles.code === RoleCode.USER && userPermissions.includes(permission)) {
return true
}
}
return false
}
首先,未登录状态下试下
没问题,让我们登录管理员再试下,添加成功
这里面用到的登录就是常规的,登录完之后得到token,把token放在缓存里面,在请求的时候把token放在请求头里面,服务端拿这个token去做校验,校验通过拿到用户信息及用户角色信息,根据角色信息判断是否有改权限,从而继续后面的操作
到这里一个简单的用户管理系统就基本完成了,看到这里的是默认会nest的,所以中间很多nest的基础部分就没有细讲了