|
- const Base = require('../base');
- const svgCaptcha = require('svg-captcha');
-
- module.exports = class extends Base {
- // 登录页面
- async loginAction() {
- // 已登录状态访问登录页,自动退出
- if (this.cookie('admin_token')) {
- this.cookie('admin_token', null);
- }
- this.assign('siteConfig', {});
- this.assign('now_year', new Date().getFullYear());
- return this.display();
- }
-
- // 图形验证码
- async captchaAction() {
- const captcha = svgCaptcha.create({
- size: 4,
- ignoreChars: '0oO1lIi',
- noise: 3,
- color: true,
- background: '#f0f2f5',
- width: 120,
- height: 40
- });
- // 存入session
- await this.session('captcha', captcha.text.toLowerCase());
- this.ctx.type = 'image/svg+xml';
- this.ctx.body = captcha.data;
- }
-
- // 登录接口
- async doLoginAction() {
- const { username, password, remember, captcha } = this.post();
-
- if (!username || !password) {
- return this.fail('请输入用户名和密码');
- }
-
- // 验证码校验
- if (!captcha) {
- return this.fail('请输入验证码');
- }
- const sessionCaptcha = await this.session('captcha');
- // 用完即清
- await this.session('captcha', null);
- if (!sessionCaptcha || captcha.toLowerCase() !== sessionCaptcha) {
- return this.fail('验证码错误');
- }
-
- // 查找用户(不限status,锁定判断在后面)
- const user = await this.model('admin_user')
- .where({ username, is_deleted: 0 })
- .find();
-
- if (think.isEmpty(user)) {
- return this.fail('用户名或密码错误');
- }
-
- // 账号停用
- if (user.status !== 1) {
- return this.fail('账号已被禁用,请联系管理员');
- }
-
- // 锁定判断:当日错误>=5次
- const today = new Date().toISOString().slice(0, 10);
- const failDate = user.login_fail_date ? new Date(user.login_fail_date).toISOString().slice(0, 10) : null;
- const failCount = (failDate === today) ? (user.login_fail_count || 0) : 0;
-
- if (failCount >= 5) {
- return this.fail('密码错误次数过多,账号已锁定,请联系管理员或次日自动解锁');
- }
-
- // 密码验证
- if (user.password !== think.md5(password)) {
- const newCount = failCount + 1;
- await this.model('admin_user').where({ id: user.id }).update({
- login_fail_count: newCount,
- login_fail_date: today
- });
- const remain = 5 - newCount;
- if (remain <= 0) {
- return this.fail('密码错误次数过多,账号已锁定,请联系管理员或次日自动解锁');
- }
- return this.fail(`密码错误,还剩${remain}次机会`);
- }
-
- // 登录成功,清除错误计数,更新登录信息
- await this.model('admin_user').where({ id: user.id }).update({
- login_fail_count: 0,
- login_fail_date: null,
- last_login_time: think.datetime(),
- last_login_ip: this.ctx.ip || ''
- });
-
- // 生成JWT Token
- const token = Base.generateToken({
- id: user.id,
- username: user.username,
- role_id: user.role_id
- });
-
- const cookieOpts = {
- httpOnly: true,
- path: '/'
- };
- if (remember) {
- cookieOpts.maxAge = Base.JWT_EXPIRES_IN * 1000;
- }
- this.cookie('admin_token', token, cookieOpts);
-
- this.adminUser = { id: user.id, username: user.username };
- await this.log('login', '系统', `${user.username} 登录系统`);
-
- return this.success({ token });
- }
-
- // 退出登录
- async logoutAction() {
- if (this.adminUser) {
- await this.log('logout', '系统', `${this.adminUser.username} 退出系统`);
- }
- this.cookie('admin_token', null);
- return this.redirect('/admin/login.html');
- }
- };
|