Skip to content
关注公众号,获取新课通知

登录功能


配置:config/config.default.js

js
config.session = {
  // 在有些场景下,我们希望用户如果长时间都在访问我们的站点,则延长他们的 Session 有效期,不让用户退出登录态
  renew: true,
  // key 代表了存储 Session 的 Cookie 键值对的 key 是什么
  key: "EGG_SESS",
  // 最长保存时间(毫秒)
  maxAge: 24 * 3600 * 1000 * 30, // 30 天
  // 设置键值对是否可以被 js 访问,默认为 true,不允许被 js 访问。
  httpOnly: true,
  // 加密
  encrypt: true,
};

控制器:app/controller/admin/home.js

js
// 引入crypto
const crypto = require('crypto');
// 登录页
    async login() {
        const { ctx } = this;
        let toast = ctx.cookies.get('toast',{ encrypt: true });
        toast = toast ? JSON.parse(toast) : null
        await ctx.render('admin/home/login.html',{
            toast
        });
    }

    // 登录逻辑
    async loginevent() {
        const { ctx, app } = this;
        // 参数验证
        ctx.validate({
            username: {
                type: 'string',
                required: true,
                desc: '用户名'
            },
            password: {
                type: 'string',
                required: true,
                desc: '密码'
            },
        });
        let { username, password } = ctx.request.body;
        // 验证该用户是否存在|验证该用户状态是否启用
        let manager = await app.model.Manager.findOne({
            where: {
                username,
            }
        });
        if (!manager) {
            ctx.throw(400, '用户不存在或已被禁用');
        }
        // 验证密码
        await this.checkPassword(password, manager.password);

        // 记录到session中
        ctx.session.auth = manager

        return ctx.apiSuccess('ok');
    }
	// 验证密码
    async checkPassword(password, hash_password) {
        // 先对需要验证的密码进行加密
        const hmac = crypto.createHash("sha256", this.app.config.crypto.secret);
        hmac.update(password);
        password = hmac.digest("hex");
        let res = password === hash_password;
        if (!res) {
            this.ctx.throw(400, '密码错误');
        }
        return true;
    }

模板:app/view/admin/home/login.html

html
{% extends "admin/layout/main.html" %}

{% block title %} 后台登录 {% endblock %}

{% block body %}
<div class="main-wrapper login-body">
    <div class="login-wrapper">
        <div class="container">
            <div class="loginbox">
                <div class="login-left">
                    <img class="img-fluid" src="/public/assets/img/logo (1).png" alt="Logo">
                </div>
                <div class="login-right">
                    <div class="login-right-wrap">
                        <h1>登 录</h1>
                        <p class="account-subtitle">Access to our dashboard</p>

                        <!-- Form -->
                        <form>
                            <div class="form-group">
                                <input class="form-control" type="text" placeholder="输入用户名..." v-model="form.username">
                            </div>
                            <div class="form-group">
                                <input class="form-control" type="text" placeholder="输入密码..." v-model="form.password">
                            </div>
                            <div class="form-group">
                                <button class="btn btn-primary btn-block" type="submit" @click.stop.prevent="submit">登 录</button>
                            </div>
                        </form>

                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block js %}
    <script>
    new Vue({
        el: '#vueapp',
        data:function(){
            return {
                form:{
                    username:"",
                    password:""
                }
            }
        },
        mounted() {
            {% if toast %}
                this.$refs.toast.show({
                    msg: "{{toast.msg}}",
                    type: "{{toast.type}}",
                })
            {% endif %}
        },
        methods: {
            submit:function(){
                var _t = this
                $.ajax({
                    type: "POST",
                    contentType: "application/json;charset=UTF-8",
                    url: "/admin/loginevent?_csrf={{ctx.csrf|safe}}",
                    data: JSON.stringify(this.form),
                    success: function (result) {
                        _t.$refs.toast.show({
                            msg: "登录成功",
                            type:"success",
                            success:function(){
                                window.location.href = "/admin"
                            },
                            delay:1000
                        })
                    },
                    error: function (e) {
                        _t.$refs.toast.show({
                            msg: e.responseJSON.data
                        })
                    }
                });
            }
        },
    })
    </script>
{% endblock %}

主布局2:app/view/admin/layout/main.html

html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
    <title>{% block title %}后台{% endblock %} - 直播后台 </title>

    <!-- Favicon -->
    <link rel="shortcut icon" type="image/x-icon" href="/public/assets/img/favicon.png">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="http://cdn.bootstrapmb.com/bootstrap/4.3.1/css/bootstrap.min.css">

    <!-- Fontawesome CSS -->
    <link rel="stylesheet" href="/public/assets/css/font-awesome.min.css">

    <!-- Main CSS -->
    <link rel="stylesheet" href="/public/assets/css/style.css">

    <!--[if lt IE 9]>
			<script src="/public/assets/js/html5shiv.min.js"></script>
			<script src="/public/assets/js/respond.min.js"></script>
        <![endif]-->
    {% block css %}{% endblock %}
    <!-- jQuery -->
    <script src="/public/assets/js/jquery-3.2.1.min.js"></script>

    <!-- Bootstrap Core JS -->
    <script src="/public/assets/js/popper.min.js"></script>
    <script src="http://cdn.bootstrapmb.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

    <!-- Custom JS -->
    <script src="/public/assets/js/script.js"></script>
    <script src="/public/assets/js/vue.min.js"></script>
    <script src="/public/assets/js/vue.components.js"></script>
</head>

<body>

    <div id="vueapp">
        {% block body %}{% endblock %}
        <confirm ref="confirm"></confirm>
        <toast ref="toast"></toast>
    </div>
    <!-- /Main Wrapper -->

    {% block js %}{% endblock %}
</body>

</html>

路由:app/router.js

js
router.get("/admin/login", controller.admin.home.login);
router.post("/admin/loginevent", controller.admin.home.loginevent);