前面我们已经搭建好后台的脚手架了,接着就是要开始大展身手的表演代码技能了。
在开始实际功能模块的编写之前,我们还需要实现重要的一步,就是后台管理员的登录和退出、管理员账号的修改等。
后台登录界面的设计
后台登录界面不需要搞得太复杂,layuiAdmin默认已经有了,我们直接拿来主义使用就可以了。
后台登录界面前端代码
我们在manage/src/views/目录下创建user文件夹,在里面增加login.html文件:
<script type="text/html" template></script>
<div class="layadmin-user-login layadmin-user-display-show" id="LAY-user-login" style="display: none;">
<div class="layadmin-user-login-main">
<div class="layadmin-user-login-box layadmin-user-login-header">
<h2>后台管理系统</h2>
</div>
<div class="layadmin-user-login-box layadmin-user-login-body layui-form">
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-username" for="LAY-user-login-username"></label>
<input type="text" name="user_name" id="LAY-user-login-username" lay-verify="required" placeholder="用户名" class="layui-input">
</div>
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LAY-user-login-password"></label>
<input type="password" name="password" id="LAY-user-login-password" lay-verify="required" placeholder="密码" class="layui-input">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid" lay-submit lay-filter="admin-login">登 入</button>
</div>
</div>
</div>
<div class="layui-trans layadmin-user-login-footer">
<p>© 2020 <a href="https://www.kandaoni.com/" target="_blank">www.kandaoni.com</a></p>
</div>
</div>
<script>
layui.use('user', layui.factory('user'));
</script>
登录界面有两个重要的信息,一个是用户名,一个是密码。基本上和前端登录的时候一致,这里为了方便起见,也没有增加验证码环节,后面有需要的时候,我们再回来补充。
接着在manage/src/controller文件夹中,增加user.js:
/**
@Name:layuiAdmin 用户登入和注册等
@Author:贤心
@Site:http://www.layui.com/admin/
@License: LPPL
*/
layui.define('form', function(exports){
var $ = layui.$
,layer = layui.layer
,laytpl = layui.laytpl
,setter = layui.setter
,view = layui.view
,admin = layui.admin
,form = layui.form
,router = layui.router()
,search = router.search;
//提交
form.on('submit(admin-login)', function(obj){
//请求登入接口
admin.req({
url: '/user/login'
,type: 'post'
,data: obj.field
,done: function(res){
//登入成功的提示与跳转
layer.msg('登入成功', {
offset: '15px'
,icon: 1
,time: 1000
}, function(){
location.hash = search.redirect ? decodeURIComponent(search.redirect) : '/';
});
}
});
});
//对外暴露的接口
exports('user', {});
});
js部分代码很简单,因为整个登录界面,我们只需要有账号密码,和登录按钮就可以,因此这里只有监听登录按钮的提交操作。在登录完成后,我们就跳转到首页,供后续继续操作。
后端登录功能golang逻辑
为了区分后台和前台的后端代码,我们在controller文件夹下,单独为后台增加一个文件夹manageController
,用来统一存放后台的后端代码。
接着我们在controller/manageController/文件夹下创建一个user.go:
package manageController
import (
"github.com/kataras/iris/v12"
"irisweb/config"
"irisweb/controller"
"irisweb/middleware"
)
func UserLogin(ctx iris.Context) {
//复用 AdminLoginForm
controller.AdminLoginForm(ctx)
}
func UserLogout(ctx iris.Context) {
session := middleware.Sess.Start(ctx)
session.Delete("adminId")
ctx.JSON(iris.Map{
"code": config.StatusOK,
"msg": "已退出登录",
})
}
这里面的golang代码比较简单,登录的时候,直接复用 controller.AdminLoginForm(ctx) 代码就可以了。退出登录则是在session中,三处adminId标记即可。
在接收数据的时候,我们需要定义一个structAdmin
来完成接收。打开request/admin.go,添加上如下代码:
type Admin struct {
UserName string `json:"user_name" validate:"required"`
Password string `json:"password" validate:"required"`
}
接着我们增加登录退出的路由:
func manageRoute(app *iris.Application) {
manage := app.Party("/manage", controller.Inspect)
{
manage.HandleDir("/", fmt.Sprintf("%smanage", config.ExecPath))
manage.Post("/user/login", manageController.UserLogin)
user := manage.Party("/user", middleware.ManageAuth)
{
user.Post("/logout", manageController.UserLogout)
}
}
}
使用manage.HandleDir("/", fmt.Sprintf("%smanage", config.ExecPath))
来绑定我们建立的后台目录manage
。
用户退出需要先检查用户是否登录,因此,这里还需要增加后台授权中间件ManageAuth
,编辑middleware/auth.go,增加ManageAuth
函数:
func ManageAuth(ctx iris.Context) {
//后台管理强制要求登录
adminId := ctx.Values().GetIntDefault("adminId", 0)
if adminId == 0 {
ctx.JSON(iris.Map{
"code": config.StatusNoLogin,
"msg": "请登录",
})
return
}
ctx.Next()
}
因为后台的交互是前后端分离的,因此都使用json来交互。这里判断如果没有登录,则返回一个提示登录的json。
管理员账面密码修改
上面已完成登录退出操作,我们接着实现管理员账号、密码的修改操作。
管理员账号的前端html
在manage/src/views/user文件夹下,新增detail.html:
<title>管理员</title>
<div class="layui-card layadmin-header">
<div class="layui-breadcrumb" lay-filter="breadcrumb">
<a lay-href="">后台首页</a>
<a><cite>管理员</cite></a>
</div>
</div>
<div class="layui-fluid">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-header">管理员修改</div>
<div class="layui-card-body" pad15>
<div class="layui-form" lay-filter="">
<script type="text/html" template lay-url="/user/detail"></script>
<div class="layui-form-item">
<label class="layui-form-label">当前密码</label>
<div class="layui-input-inline">
<input type="password" name="old_password" placeholder="如不需修改密码,请留空" lay-verType="tips"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">新密码</label>
<div class="layui-input-inline">
<input type="password" name="password" placeholder="如不需修改密码,请留空" lay-verify="pass" lay-verType="tips"
autocomplete="off" id="LAY_password" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">6到20个字符</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">确认新密码</label>
<div class="layui-input-inline">
<input type="password" name="re_password" placeholder="如不需修改密码,请留空" lay-verify="repass"
lay-verType="tips" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="change-admin">确认修改</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
layui.use('user', layui.factory('user'));
</script>
修改账号密码这里,我们需要提供用户名、当前密码、新的密码、重复新的密码四个表单,当然新密码不是必须提供的,如果不需要修改密码,则留空即可。
管理员账号的前端js
我们继续打开manage/src/controller/user.js,添加验证代码:
/**
@Name:layuiAdmin 用户登入和注册等
@Author:贤心
@Site:http://www.layui.com/admin/
@License: LPPL
*/
layui.define('form', function(exports){
var $ = layui.$
,layer = layui.layer
,laytpl = layui.laytpl
,setter = layui.setter
,view = layui.view
,admin = layui.admin
,form = layui.form
,router = layui.router()
,search = router.search;
//自定义验证
form.verify({
username: function(value, item){ //value:表单的值、item:表单的DOM对象
if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){
return '用户名不能有特殊字符';
}
if(/(^\_)|(\__)|(\_+$)/.test(value)){
return '用户名首尾不能出现下划线\'_\'';
}
if(/^\d+\d+\d$/.test(value)){
return '用户名不能全为数字';
}
}
//我们既支持上述函数式的方式,也支持下述数组的形式
//数组的两个值分别代表:[正则匹配、匹配不符时的提示文字]
,pass: [
/^[\S]{6,20}$/
,'密码必须6到20位,且不能出现空格'
]
});
//提交
form.on('submit(admin-login)', function(obj){
//请求登入接口
admin.req({
url: '/user/login'
,type: 'post'
,data: obj.field
,done: function(res){
//登入成功的提示与跳转
layer.msg('登入成功', {
offset: '15px'
,icon: 1
,time: 1000
}, function(){
location.hash = search.redirect ? decodeURIComponent(search.redirect) : '/';
});
}
});
});
// 修改管理员
form.on('submit(change-admin)', function(obj){
if(obj.field.password != obj.field.re_password) {
return layer.msg("两次输入的新密码不一致。请重新输入");
}
admin.req({
url: '/user/detail'
,type: 'post'
,data: obj.field
,done: function(res){
if(res.code === 0) {
layer.msg(res.msg, {
offset: '15px'
,icon: 1
,time: 1000
});
} else {
layer.msg(res.msg);
}
}
});
});
//对外暴露的接口
exports('user', {});
});
修改管理员账号和密码的时候,我们需要做一些基本的验证操作,比如用户账号的规范、密码长度等信息的验证。最后就是表单的提交了。
管理员账号修改的golang后端逻辑代码
为了实现账号修改,我们还需要在后端接收提交过来的数据。
编辑controller/manageController/user.go:
func UserDetail(ctx iris.Context) {
adminId := uint(ctx.Values().GetIntDefault("adminId", 0))
admin, err := provider.GetAdminById(adminId)
if err != nil {
ctx.JSON(iris.Map{
"code": config.StatusFailed,
"msg": "用户不存在",
})
return
}
ctx.JSON(iris.Map{
"code": config.StatusOK,
"msg": "",
"data": admin,
})
}
func UserDetailForm(ctx iris.Context) {
var req request.ChangeAdmin
if err := ctx.ReadJSON(&req); err != nil {
ctx.JSON(iris.Map{
"code": config.StatusFailed,
"msg": err.Error(),
})
return
}
adminId := uint(ctx.Values().GetIntDefault("adminId", 0))
admin, err := provider.GetAdminById(adminId)
if err != nil {
ctx.JSON(iris.Map{
"code": config.StatusFailed,
"msg": "用户不存在",
})
return
}
if !admin.CheckPassword(req.OldPassword) {
ctx.JSON(iris.Map{
"code": config.StatusFailed,
"msg": "当前密码不正确",
})
return
}
admin.UserName = req.UserName
admin.Password = admin.EncryptPassword(req.Password)
err = admin.Save(config.DB)
if err != nil {
ctx.JSON(iris.Map{
"code": config.StatusFailed,
"msg": "更新信息出错",
})
return
}
ctx.JSON(iris.Map{
"code": config.StatusOK,
"msg": "管理员信息已更新",
})
}
增加了userDetail()
、userDetailForm()
函数,他们分别的作用是一个是给前端提供数据userDetail()
,一个是接收并处理前端提交过来的数据userDetailForm()
。
在接收数据的时候,我们需要定义一个structChangeAdmin
来完成接收。打开request/admin.go,添加上如下代码:
type ChangeAdmin struct {
UserName string `json:"user_name" validate:"required"`
OldPassword string `json:"old_password"`
Password string `json:"password"`
RePassword string `json:"re_password"`
}
如果用户提交的表单中,包含密码的修改,则,我们需要先验证旧密码是否正确,如果正确了,再进行新密码的编码并更新数据库信息。
最后我们需要将他们添加到路由中,便可正常访问。编辑route/manage.go:
user := manage.Party("/user", middleware.ManageAuth)
{
user.Get("/detail", manageController.UserDetail)
user.Post("/detail", manageController.UserDetailForm)
user.Post("/logout", manageController.UserLogout)
}
至此我们实现的后台的第一步。完成之后,我们启动golang项目来验证下结果,如果不出意外,就可以登录、退出、修改管理员账号密码信息了。
教程用例源码
完整的项目示例代码托管在GitHub上,访问github.com/fesiong/goblog 可以查看完整的教程项目源代码,建议在查看教程的同时,认真对照源码,可以有效提高码代码速度和加深对博客项目的认识。建议直接fork一份来在上面做修改。欢迎点Star。