前面我们已经初始化博客系统了,接着,我们再做管理员登录和权限控制判断。我们将分别介绍使用sessions、cookie实现登录控制问题。

sessions的使用

github.com/kataras/iris/v12/sessions
var Sess = sessions.New(sessions.Config{Cookie: "irisweb"})
Sess.Start(ctx)hasLoginctx.Values().Set()hasLogin
func Auth(ctx iris.Context) {
    //检查登录状态
    session := Sess.Start(ctx)
    hasLogin := session.GetBooleanDefault("hasLogin", false)
    ctx.Values().Set("hasLogin", hasLogin)
    ctx.ViewData("hasLogin", hasLogin)

    ctx.Next()
}

管理员登录

博客管理员的登录,得首先有一个可供登录的页面,以及处理登录的控制器。

管理员登录页面

我们在template文件夹下创建一个admin文件夹,并在里面新建一个login.html:

{% include "partial/header.html" %}
<div class="admin-login">
    <div class="login-main">
        <div class="login-box login-header">
            <h2>{{SiteName}}</h2>
            <p>一个由irisweb框架编写的简单的博客系统</p>
        </div>
        <div class="login-box login-body layui-form">
            <div class="layui-form-item">
                <label class="login-icon layui-icon layui-icon-username" for="login-username"></label>
                <input type="text" name="user_name" id="login-username" lay-verify="required" placeholder="用户名" class="layui-input">
            </div>
            <div class="layui-form-item">
                <label class="login-icon layui-icon layui-icon-password" for="login-password"></label>
                <input type="password" name="password" id="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="login-submit">登 录</button>
            </div>
        </div>
    </div>

    {% include "partial/footer.html" %}
</div>

上面是登录页面的html代码,同样地,我们引入了头部和尾部的代码片段。管理员登录表单包含两个字段,一个是管理员用户名(user_name),一个是管理员密码(password),它们都是必须字段。这里为了简单,没有加入验证码验证部分的代码。如果再严谨一点,这里是还需要添加验证码的。

提交表单是js代码

public/static/js/app.js
form.on('submit(login-submit)', function(obj){
        $.post('/admin/login', obj.field, function(res) {
                if(res.code === 0) {
                        layer.msg('登录成功', {
                                offset: '15px'
                                ,icon: 1
                                ,time: 1000
                        }, function(){
                                window.location.href = '/';
                        });
                } else {
                        layer.msg(res.msg);
                }
        });
});
/admin/login

管理员登录页面的控制器

接着,我们在controller目录下,创建一个admin.go文件,用来存放登录页面的控制器和登录处理过程的控制器。在里面增加AdminLogin()函数:

func AdminLogin(ctx iris.Context) {

    ctx.View("admin/login.html")
}

这个控制器很简单,只需要用来承载登录页面即可。

管理员登录处理逻辑控制器

接着,我们还需要创建一个接收登录页面提交上来的信息,完成登录过程。
我们先定义一个接收登录信息的结构体。我们在request文件夹下,新建一个Admin.go文件,添加如下代码:

package request

type Admin struct {
    UserName string `form:"user_name" validate:"required"`
    Password string `form:"password" validate:"required"`
}
AdminLoginForm()
func AdminLoginForm(ctx iris.Context) {
    var req request.Admin
    if err := ctx.ReadForm(&req); err != nil {
        ctx.JSON(iris.Map{
            "code": config.StatusFailed,
            "msg":  err.Error(),
        })
        return
    }

    admin, err := provider.GetAdminByUserName(req.UserName)
    if err != nil {
        ctx.JSON(iris.Map{
            "code": config.StatusFailed,
            "msg":  err.Error(),
        })
        return
    }

    if !admin.CheckPassword(req.Password) {
        ctx.JSON(iris.Map{
            "code": config.StatusFailed,
            "msg":  "登录失败",
        })
        return
    }

    session := middleware.Sess.Start(ctx)
    session.Set("hasLogin", true)

    ctx.JSON(iris.Map{
        "code": 0,
        "msg":  "登录成功",
        "data": 1,
    })
}
ctx.ReadFormCheckPassword()
func (admin *Admin) CheckPassword(password string) bool {
    if password == "" {
        return false
    }

    byteHash := []byte(admin.Password)
    bytePass := []byte(password)
    err := bcrypt.CompareHashAndPassword(byteHash, bytePass)
    if err != nil {
        return false
    }

    return true
}
CheckPassword()Adminpasswordgolang.org/x/crypto/bcryptbcrypt.CompareHashAndPassword()admin.PasswordpasswordSess
  session := middleware.Sess.Start(ctx)
    session.Set("hasLogin", true)

退出登录控制器

AdminLogout()
func AdminLogout(ctx iris.Context) {
    session := middleware.Sess.Start(ctx)
    session.Delete("hasLogin")

    ctx.Redirect("/")
}
hasLoginsession.Delete()

配置登录路由

上面登录页面和登录处理逻辑相关的控制器写好了,我们还需要将它注入到路由中,才能从浏览器中访问到。我们现在打开route/base.go文件,在Register中增加三个路由:

  admin := app.Party("/admin", controller.Inspect)
    {
        admin.Get("/login", controller.AdminLogin)
        admin.Post("/login", controller.AdminLoginForm)
        admin.Get("/logout", controller.AdminLogout)
    }
app.Party()

验证结果

我们重启一下项目,在浏览器中访问看看效果,验证下登录过程是否正常。如果不出意外可以看到这样的画面:
描述

输入正确的账号、密码,就可以完成登录了。

教程用例源码

完整的项目示例代码托管在GitHub上,访问github.com/fesiong/goblog 可以查看完整的教程项目源代码,建议在查看教程的同时,认真对照源码,可以有效提高码代码速度和加深对博客项目的认识。建议直接fork一份来在上面做修改。欢迎点Star。