# 一、配置session
管理员登录信息我们采用session存储,先配置一下session
config/config.default.js//配置session config.session = { //在有些场景下,我们希望用户如果长时间都在访问我们的站点 //则延长他们的session有效期,不让用户退出状态 renew:true, //key代表存储session的cookie键值对的 key:'EGG_SESS', //最长保留时间(毫秒) maxAge:24*3600*1000*30,//30天 //设置键值对是否可以被js访问,默认true,不容许被js访问 httpOnly:true, //加密 encrypt:true, };
# 二、定义控制器和路由
- 定义一个控制器将后台首页、管理员登录退出等功能写在里面
新建控制器app/controller/admin/home.js'use strict'; // 哈希函数加密 const crypto = require('node:crypto'); const Controller = require('egg').Controller; class HomeController extends Controller { //管理员登录页面---后台登录页面 async login() { let { ctx } = this; await ctx.render('admin/home/login.html'); } //管理员登录逻辑 async loginevent() { let { ctx, app } = this; //参数验证 this.ctx.validate({ username: { type: 'string', //参数类型 required: true, //是否必须 // defValue: '', desc: '管理员账号' //字段含义 }, password: { type: 'string', required: true, // defValue: '', desc: '管理员密码' }, }); // 拿参数 let { username, password } = ctx.request.body; // 判断管理员是否存在 let manager = await ctx.model.Manager.findOne({ where: { username: username } }); // 不存在则抛出异常 if (!manager) { ctx.throw(400, '该管理员不存在或者被禁用了'); } // 存在则验证密码 await this.checkPassword(password, manager.password); //存储在session中,定义session中的一个属性auth存储登录信息 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; } } module.exports = HomeController;
- 定义路由
app/router/admin.js// 管理员登录界面 router.get('/admin/login', controller.admin.home.login); //管理员登录逻辑 router.post('/admin/loginevent', controller.admin.home.loginevent);
- 登录页面
app/view/admin/home/login.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>后台管理中心 - 登录</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]--> <!-- 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.2.7.0.min.js"></script> <script src="/public/assets/js/vue.component.js"></script> </head> <body> <!-- Main Wrapper --> <div class="main-wrapper login-body" id="vueapp"> {# 消息提示组件 #} <toast ref="toast"></toast> {# 弹出确认框组件 #} <confirm ref="confirm"></confirm> <div class="login-wrapper"> <div class="container"> <div class="loginbox"> <div class="login-left"> <!-- <img class="img-fluid" src="/public/assets/img/logo.png" alt="Logo"> --> <div class="img-fluid"> <h3 class="text-white">后台管理中心入口</h3> </div> </div> <div class="login-right"> <div class="login-right-wrap"> <h1>登 录</h1> <p class="account-subtitle">后台管理中心欢迎您</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> <!-- /Main Wrapper --> <script> var Vueapp = new Vue({ el:'#vueapp', data(){ return { form:{ username:'', password:'', } } }, methods:{ submit(){ console.log('执行登录',this.form); } } }); </script> </body> </html>
# 三、实现管理员登录功能
app/view/admin/home/login.html... <script> var Vueapp = new Vue({ el:'#vueapp', data(){ return { form:{ username:'', password:'', } } }, methods: { submit(){ console.log('提交登录',this.form); $.ajax({ type: 'POST', url: "/admin/loginevent?_csrf={{ctx.csrf|safe}}", contentType:'application/json;charset=UTF-8;', data:JSON.stringify(this.form), success: function (response, stutas, xhr) { console.log(response) Vueapp.$refs.toast.show({ msg:"登录成功", type:'success', delay:1000, success:function(){ // 跳转到某个页面 window.location.href = "/admin/manager/index"; } }); }, error:function(e){ console.log(e) Vueapp.$refs.toast.show({ msg:e.responseJSON.data, type:'danger', delay:3000 }); } }); } } }); </script> </body> </html>
# 四、权限验证,即后台所有栏目需要管理员登录才能查看
# ① 需要新建一个中间件做权限验证,
app/middleware/admin_auth.jsmodule.exports = (option, app)=>{ return async function adminAuth(ctx,next){ //拿到管理员的登录信息 // console.log(ctx.session.auth); if(!ctx.session.auth){ ctx.toast('请先登录!','danger'); return ctx.redirect('/admin/login'); } await next(); if(ctx.status === 404){ await ctx.pageFail('页面不存在'); } } }# ② 中间件配置
config/config.default.js... config.middleware = ['errorHandler','adminAuth']; config.adminAuth = { ignore:[ "/admin/login", "/admin/loginevent", ], }; ...# ③ 控制器管理员登录方法完善
app/controller/admin/home.js//管理员登录页面---后台登录页面 async login() { // const { ctx,app } = this; let toast = this.ctx.cookies.get('toast',{encrypt: true}); toast = toast ? JSON.parse(toast) : null; await this.ctx.render('admin/home/login.html',{ toast }); }# ④ 登录页面提示请先登录
app/view/admin/home/login.html... <script> var Vueapp = new Vue({ ... //页面加载完毕 mounted(){ var toast = "{{toast.msg}}"; if(this.$refs.toast && toast){ this.$refs.toast.show({ msg:'{{toast.msg}}', type:'{{toast.type}}', delay:1500 }); } }, ... }); </script>
# 五、管理员退出登录
# ① 退出登录方法
app/controller/admin/home.js//管理员退出登录 async logout(){ let {ctx} = this; //清除session ctx.session.auth = null; ctx.toast('退出登录成功','success'); ctx.redirect('/admin/login'); }# ② 定义路由
app/router/admin.js//管理员退出登录 router.get('/admin/logout', controller.admin.home.logout);# ③ 模版页面退出
app/view/admin/layout/_header.html<a class="dropdown-item" href="/admin/logout">退出登录</a>