Zhiqim Manager(知启蒙管理台)是知启蒙框架中最核心的基础组件,大部分后台组件和产品都依赖该组件。因为管理台提供了核心的系统配置、菜单、操作员、部门、角色等权限功能,以及6种皮肤样式可供选择

森中灵 最后提交于4月前 修复切换frame模式时未情况includeUrl
ZmrLoginPresenter.java8KB
/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_manager.htm
 *
 * Zhiqim Manager is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager.presenter;

import java.util.List;

import org.zhiqim.httpd.HttpContext;
import org.zhiqim.httpd.HttpCookie;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.context.ZmlBootstrap;
import org.zhiqim.httpd.context.ZmlContexts;
import org.zhiqim.httpd.context.core.Context;
import org.zhiqim.httpd.util.Sessions;
import org.zhiqim.httpd.validate.ones.IsNotEmpty;
import org.zhiqim.httpd.validate.ones.IsNumericLen;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.model.codes.Base64;
import org.zhiqim.kernel.model.codes.RSA;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.ZmrBootstrap;
import org.zhiqim.manager.ZmrConstants;
import org.zhiqim.manager.ZmrPassworder;
import org.zhiqim.manager.ZmrSessionUser;
import org.zhiqim.manager.dao.ZmrOperatorDao;
import org.zhiqim.manager.dao.ZmrParamDao;
import org.zhiqim.manager.dbo.ZmrMenu;
import org.zhiqim.manager.dbo.ZmrOperator;
import org.zhiqim.orm.ORM;

/**
 * 登陆控制器
 *
 * @version v1.0.0 @author liuhu 2018-8-2 新建与整理
 */
@AnAlias("ZmrLoginPresenter")
public class ZmrLoginPresenter implements ZmrConstants
{
    public static void doLogin(HttpRequest request) throws Exception
    {
        HttpContext context = request.getContext();
        
        //1.判断传入参数
        request.addValidate(new IsNotEmpty("operatorCode", "账号不能为空"));
        request.addValidate(new IsNotEmpty("operatorPass", "密码不能为空"));
        
        boolean hasVerificationCode = ZmrParamDao.hasVerificationCode();
        if(hasVerificationCode)
        {
            request.addValidate(new IsNumericLen("verificationCode", "验证码必须是4位数字", 4, 4));
        }
        
        if (!request.chkValidate())
        {
            request.setResponseError(request.getAlertMsg());
            return;
        }
        
        //2.验证码
        if(hasVerificationCode)
        {
            String verificationCode = request.getParameter("verificationCode");
            String vcode = Sessions.getSessionVerificationCode(request);
            if (!verificationCode.equals(vcode))
            {
                request.setResponseError("验证码不正确或已失效,请新输入!");
                return;
            }
        }
        
        //3.验证操作员账号是否存在、是否停用,是否组停用
        String operatorCode = request.getParameter("operatorCode");
        ZmrOperator operator = ORM.table().item(ZmrOperator.class, operatorCode);
        if(operator == null)
        {
            request.setResponseError("用户账号不正确");
            return;
        }
        
        if(!operator.isOperatorValid())
        {
            request.setResponseError("该用户已停用,不允许登录");
            return;
        }
        
        //4.验证密码
        String operatorPass = request.getParameter("operatorPass");
        
        byte[] operatorPassByte = Base64.decode(operatorPass);
        String privateKey = ZmrParamDao.getPrivateKey();
        byte[] operatorPassDecrypt = RSA.decrypt(operatorPassByte, privateKey);
        operatorPass = new String(operatorPassDecrypt, _UTF_8_C_);
        
        if (isValidateRememberPass(operatorPass))
        {//全是●的密码表示记住密码要求验证密钥
            if (!ZmrParamDao.hasRememberCode() || !ZmrParamDao.hasRememberPass() || !operatorCode.equals(request.getCookie("operatorCode")))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
            
            ZmrPassworder passworder = ZmrBootstrap.getPassworder();
            String operatorPassSecr = request.getCookie("operatorPass");
            if (!passworder.secretChk(operatorCode, operatorPass, operator.getOperatorPassSalt(), operatorPassSecr))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        else
        {//正常验证密码
            if(!ZmrOperatorDao.validatePassword(operator, operatorPass))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        
        List<ZmrMenu> menuList = ZmrOperatorDao.getOperatorMenuList(operator);
        if(menuList.isEmpty())
        {
            request.setResponseError("您暂没有任何操作权限,请与管理员联系");
            return;
        }
        
        //5.完成验证,组装会话用户
        ZmrSessionUser sessionUser = new ZmrSessionUser()
            .initOperator(operator)
            .initMenuAll(context, ZmrOperatorDao.getAllMenuList())
            .initMenuList(context, menuList);
        
        //6.判断需要保存信息到COOKIE
        if(ZmrParamDao.hasRememberCode())
        {
            boolean rememberCode = request.getParameterBoolean("rememberCode");
            boolean rememberPass = request.getParameterBoolean("rememberPass");
            int day30 = 60*60*24*30;
            
            HttpResponse response = request.getResponse();
            if(rememberPass)
            {//勾选了记住密码,则一定记住登录名
                ZmrPassworder passworder = ZmrBootstrap.getPassworder();
                String operatorSecr = passworder.secret(operatorCode, operatorPass, operator.getOperatorPassSalt());
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", operatorSecr, day30));
            }
            else if (rememberCode)
            {//只记住用户账号
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
            else
            {//否则设置值为空
                response.addCookie(new HttpCookie("operatorCode", "", day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
        }
        
        //7.判断是否填写了主页跳转地址
        String mainUrlDefault = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_DEFAULT));
        String mainUrlParam = request.getRootPath(ZmlContexts.parseZmlContent(request, ZmrParamDao.getMainUrl()));
        if (!ZmrParamDao.isThemeFrame())
        {//没用框架,判断mainUrl配置,有值取mainUrlParam,为空取缺省mainUrlDefault
            request.bindSessionUser(sessionUser);
            request.setResponseResult(Validates.isEmptyBlank(mainUrlParam)?mainUrlDefault:mainUrlParam);
        }
        else
        {//有用框架,判断mainUrl配置,有值传includeUrl为mainUrlParam,为空传welcomeUrl,返回mainUrlDefault
            String welcomeUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_WELCOME));
            sessionUser.initWelcomeUrl(welcomeUrl);
            sessionUser.initIncludeUrl(Validates.isEmptyBlank(mainUrlParam)?welcomeUrl:mainUrlParam);
            
            request.bindSessionUser(sessionUser);
            request.setResponseResult(mainUrlDefault);
        }
        
        //8.最后回调登录
        ZmlBootstrap bootstrap = ((Context)context).getBootstrap();
        bootstrap.event(request, ZMR_EVENT_LOGINED);
        
        //9.记录登录操作日志
        ZmrOperatorDao.addOperateLog(request, "登录");
    }
    
    private static boolean isValidateRememberPass(String operatorPass)
    {
        for (int i=0;i<operatorPass.length();i++)
        {
            if (operatorPass.charAt(i) != '●')
                return false;
        }
        return true;
    }
}