技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(一):管理员功能的实现
相关文章:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-1.工具和本地环境
…
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-8.模型的关联——无限层级分类
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(一):管理员功能的实现
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(二):用户登录和密码验证
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(三):登录的token验证
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-10.生产环境编译
…
1.admin端制作前端页面
(1)分别创建创建管理员页面AdminSet.vue和管理员列表页面AdminList。
(2)前端路由使左侧菜单跳转到新创建的两个页面:
Main.vue:
routes/index.js:
(3)编辑管理员页面:
AdminSet.vue:
<template>
<div>
<h1>{{id ? '编辑' : '创建'}}管理员</h1>
<el-form label-width="80px" style="margin-top:20px;" @submit.native.prevent="save">
<el-form-item label="用户名">
<el-input v-model="model.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="model.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
id: {}
},
data(){
return {
model: {},
parentOptions: [],
}
},
methods: {
async save(){
let res
if(this.id){
res = await this.$http.put('rest/admin/' + this.id, this.model)
}else{
res = await this.$http.post('rest/admin', this.model)
}
console.log("en?",res)
this.$router.push('/admins/list')
this.$message({
type: 'success',
message: '保存成功'
})
},
async fetch(){
const res = await this.$http.get('rest/admins/' + this.id)
this.model = res.data
},
},
created(){
this.id && this.fetch()
}
}
</script>
AdminList.vue:
<template>
<div>
<h1>分类列表</h1>
<el-table :data="items">
<el-table-column prop="_id" label="ID" width="220">
</el-table-column>
<el-table-column prop="username" label="用户名">
</el-table-column>
<!-- 列表页没必要将用户密码显示 -->
<!-- <el-table-column prop="password" label="密码">
</el-table-column> -->
<el-table-column
fixed="right"
label="操作"
width="100">
<template slot-scope="scope">
<el-button type="text" size="small" @click="$router.push('/admins/edit/' + scope.row._id)">编辑</el-button>
<el-button @click="remove(scope.row)" type="text" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
items: []
}
},
methods: {
async fetch(){
const res = await this.$http.get('rest/admins')
this.items = res.data
},
remove(row){
this.$confirm('是否确定要删除"' + row.name + '"的账号?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
// 要想使用await,函数必须使用async
// await异步执行,待调用接口获取数据完成后再将值传给res,进行下一步操作
const res = await this.$http.delete('rest/admins/' + row._id)
this.$message({
type: 'success',
message: '删除成功!'
});
if(res.status == 200){
// 接口调用成功后,刷新页面
this.fetch()
}
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
created() {
this.fetch()
}
}
</script>
2.管理员接口
将之前测试用的user表和user接口改为admin表和admin接口:
(1)将页面中所有user字段改成admin:
(2)将需要首字母大写的模型名改成Admin,替换功能不区分大小写,所以我们找带models字段的地方修改:
(3)修改user模型,改成admin,包括文件名和模型名:
修改前
修改后
(4)编译启动server端测试:
(5)最后,修改user表名,改为admin:
修改前
修改后
刷新管理员列表页面查看是否有数据获取到:
没有接收到数据,检查接口地址,发现传值为admins,将admins改为admin:
保存,刷新页面:
获取到之前user表测试的内容,成功。
测试新建管理员功能:
成功。
此时我们发现列表页的id没有查询出来,是因为admin模型问题,根据category模型修改admin模型:
重新编译启动server端,刷新页面测试,成功获取id:
由于AdminList.vue页面我是赋值CategoryList.vue页面,忘了修改该页名称,管理员列表名称修改一下:
此时,查询数据也没问题了,下一步测试修改数据:
没有获取到信息:
查找原因,果然还是接口名的问题,每次习惯性写成复数:
修改后刷新页面测试,没问题:
修改admin改成admin1测试:
修改功能也没问题。接下来测试删除管理员功能:
没问题,成功:
由于我们使用了restful风格的CRUD接口,所以一套增删改查接口就可以实现所有模块的增删改查,只要加入传值判断即可,所以比较方便:
3.密码加密问题
虽然我们前端的密码输入框使用了password加密,将密码转化为*号,但是想要查看用户密码还是很简单的。
我们在查看用户信息时,不光要保证用户信息安全,还要顾及用户的隐私安全。在很多时候用户为了容易记住自己的登录密码,基本上会在多个网站重复使用自己的密码,比如csdn登录的密码与qq相同。所以我们需要做到任何人包括我们自己都不可以看到用户的密码,守住作为一个合格开发者的底线和基本的职业操守。
所以我们给为一切密码进行加密。
我们常用的加密方式是MD5加密,但是MD5加密的方法是将用户密码按照规则翻译成另一传编码进行传值,是可以反向解密的一串字符。
所以我们需要使用bcrypt方法对密码进行加密。
bcryptjs的加密方式每次生成的编码是不同的,所以就算我们看到了编码,也不可能按照编码的规律反向推断出用户密码,所以说是绝对加密的。
(1)安装bcrypt包:
go get golang.org/x/crypto/bcrypt@v0.0.0-20200622213623-75b288015ac9
(2)在接口路由页面编写加密方法
// 加密密码
// 传如字符串格式的密码,输出字符串格式的加密后密码或错误值
func bcryptPsw(pwdStr string) (pwdHash string, err error) {
// 将需要加密的密码放入byte格式数组中
pwd := []byte(pwdStr)
// 通过bcrypt内部自带加密的方法对该数组进行加密
hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.MinCost)
// 如果加密过程出错,则返回错误值
if err != nil {
return
}
// 如果加密完成,则将加密后的值编译成字符串格式,返回加密后的密码
pwdHash = string(hash)
return
}
(3)下方获取表单数据并传值调用加密方法:
过程:
编译启动测试:
新建管理员测试:
没问题,一个加密的密码被传入数据库。
加密的密码不可解密,我们永远不知道用户填写了什么,只能用bcript验证方法才可进行比对(校验)登录。同时同样的密码加密后显示的值也是不同的。
如果用户忘记密码,只可修改,顶级管理员也无法找回。
4.修改密码
新建管理员功能使用了加密方法才可以让密码加密,但是修改管理员功能所用的接口并没有使用加密方法。所以通过修改功能修改的密码还是未加密状态。
所以我们同样要修改修改管理员信息的接口,使用的模型和方法相同,只需要调用加密方法即可:
编译启动,测试:
修改接口调用成功,再次进入修改页面:
没问题。
到此密码的加密问题已经实现,下篇文章我们制作登陆功能,学习bcrypt的密码校验方法。
更多设计、功能的学习经验,大家也可以去我的公众号查看!
————