<%@ page import="weaver.hrm.User" %>
<%@ page import="weaver.hrm.HrmUserVarify" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="weaver.general.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="weaver.filter.XssUtil" %>
<jsp:useBean id="baseBean" class="weaver.general.BaseBean" scope="page"/>
<jsp:useBean id="rs" class="weaver.conn.RecordSet" scope="page"/>
<%


    String method = request.getMethod();
    if (!method.equals("POST")) {
        response.getWriter().write("请求类型不允许");
        return;
    }

    User user = HrmUserVarify.getUser(request, response);
    XssUtil xssUtil = new XssUtil();
    String secondPrefixPath = xssUtil.null2String(xssUtil.getRule().get("second-prefix-path"));
    int UID = xssUtil.getIntValue("" + xssUtil.getRule().get("userID"), 1);
    if (user == null || user.getUID() != UID) {
        response.sendRedirect(secondPrefixPath + "/notice/noright.jsp");
        return;
    }

    String msg = "";
    if (errorNum >= maxErrorNum) {
        msg = "错误次数达到上限，凭证已注销，需重新登录";
        writeLog(msg);
        response.getWriter().write(msg);
        errorNum = 0;
        request.getSession().invalidate();
        response.sendRedirect("/notice/noright.jsp");
        //lockTime = new Date().getTime();
        return;
    }

    long currentTime = new Date().getTime();
    // 登录免检测
    if (authenticationSuccessTime > 0) {
        String doubleLoginCheckSuccessTime = (String) session.getAttribute("doubleLoginCheckSuccessTime");
        if (currentTime - authenticationSuccessTime < 10 * 60 * 1000 && doubleLoginCheckSuccessTime != null) {
            response.getWriter().write("1");
            return;
        } else {
            request.getSession().setAttribute("doubleLoginCheckStatus", null);
            request.getSession().setAttribute("doubleLoginCheckSuccessTime", null);
            authenticationSuccessTime = 0l;
        }
    }

    // 获取用户输入的用户名
    String userPassword = Util.null2String(request.getParameter("userpassword")).trim();
    String validateCode = Util.null2String(request.getParameter("validatecode"));
    // 用户数据判断
    if ("".equals(userPassword) || "".equals(userPassword) || "_check_".equals(userPassword)) {
        response.getWriter().write("数据不允许为空");
        return;
    }

    writeLog("client captcha：" + validateCode + " server captcha：" + request.getSession().getAttribute("validateRand"));

    // 服务器存储的验证码
    String validateRandOs = Util.null2String(request.getSession().getAttribute("validateRand"));
    if ("".equals(validateCode) || !validateCode.equalsIgnoreCase(validateRandOs)) {
        response.getWriter().write("验证码不正确");
        return;
    }
    request.getSession().setAttribute("validateRand", "");

    // rsa解密
    userPassword = decryptRsaPwd(userPassword, request);
    if (userPassword == null) {
        response.getWriter().write("解密异常!");
        return;
    }

    // sm4解密
    userPassword = decryptSm4Pwd(userPassword);
    if (userPassword == null) {
        response.getWriter().write("解密异常。");
        return;
    }

    boolean passwordCheck = false;
    String sql = "select * from hrmresourcemanager where id = ?";
    rs.executeQuery(sql, user.getUID());
    if (rs.next()) {
        String dbPwd = rs.getString("password");
        String salt = rs.getString("salt");
        passwordCheck = userPassword.length() > 0 && checkPwd(userPassword, salt, dbPwd);
    }

    if (!passwordCheck) {
        sql = "select * from hrmresource where id = ?";;
        rs.executeQuery(sql, user.getUID());
        if (rs.next()) {
            String dbPwd = rs.getString("password");
            String salt = rs.getString("salt");
            passwordCheck = userPassword.length() > 0 && checkPwd(userPassword, salt, dbPwd);
        }
    }

    writeLog("double login check >> check pwd = " + passwordCheck);

    if (!passwordCheck) {
        writeLog("loginid = " + user.getLoginid() + " UID = " + user.getUID() + " lastname = " + user.getLastname() + " 密码错误，剩余" + (maxErrorNum - errorNum) + "次");
        response.getWriter().write("密码错误，剩余" + (maxErrorNum - errorNum) + "次");
        errorNum++;
        return;
    }

    errorNum = 0;
    authenticationSuccessTime = new Date().getTime();
    request.getSession().setAttribute("doubleLoginCheckStatus", "true");
    request.getSession().setAttribute("doubleLoginCheckSuccessTime", authenticationSuccessTime + "");
    response.getWriter().write("1");


%>


<%!

    public static int errorNum = 1;
    public static int maxErrorNum = 5;
    private static long lockTime = 0L;
    private static long authenticationSuccessTime = 0L;
    private static String ENC_TYPE_SM3 = "sm3";
    private static String ENC_TYPE_MD5 = "md5";
    private static XssUtil xssUtil = new XssUtil();


    public String decryptRsaPwd(String userPassword, HttpServletRequest request) {
        try {
            String rsaIsOpen = Util.null2String(new BaseBean().getPropValue("openRSA", "isrsaopen"));
            if ("1".equals(rsaIsOpen) || userPassword.endsWith("``RSA``") || userPassword.endsWith("_check_")) {
                String tmpPwd = userPassword;
                userPassword = replaceStr(userPassword);
                Class aClass = Class.forName("weaver.rsa.security.RSA");
                Object rsaObj = aClass.newInstance();
                Method decrypt = aClass.getDeclaredMethod("decrypt", new Class[]{HttpServletRequest.class, String.class, boolean.class});
                Method getMessage = aClass.getDeclaredMethod("getMessage", new Class[]{});
                userPassword = (String) decrypt.invoke(rsaObj, new Object[]{request, userPassword, true});
                String msg = (String) getMessage.invoke(rsaObj, new Object[]{});
                if (!msg.equals("0")) {
                    writeLog("RSA 解密失败 >> oriData = " + tmpPwd + "decryptData = " + userPassword + " msg = " + msg);
                    return null;
                }
            }
            return userPassword;
        } catch (Exception e) {
            xssUtil.writeError(e);
            e.printStackTrace();
        }

        return null;
    }

    public String decryptSm4Pwd(String user_password) {
        if (user_password == null) return "";
        try {
            if (user_password.endsWith("_random_")) {
                Class aClass = Class.forName("weaver.sm.SM4Utils");
                Method decrypt = aClass.getDeclaredMethod("decrypt", new Class[]{String.class, String.class});
                BaseBean bb = new BaseBean();
                String key = Util.null2String(bb.getPropValue("weaver_client_pwd", "key"));
                if (!"".equals(key)) {
                    user_password = user_password.substring(0, user_password.lastIndexOf("_random_"));
                    //user_password = sm4.decrypt(user_password, key);
                    user_password = (String) decrypt.invoke(aClass.newInstance(), new Object[]{user_password, key});
                }
            }
            return user_password;
        } catch (Exception e) {
            xssUtil.writeError(e);
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 密码认证
     */
    public boolean checkPwd(String userPwd, String formatSalt, String dbPwd) {
        String encryptPwd = "";
        String isOpenSm3 = Util.null2String(new BaseBean().getPropValue("nonreversible_enc_type", "sm3"));
        if (isNewSM3Salt(formatSalt)) {
            encryptPwd = getEncryptSm3(userPwd, getRealSalt(formatSalt), ENC_TYPE_SM3, "UTF-8");
        } else if (isOldSM3Salt(formatSalt)) {
            encryptPwd = getEncryptSm3(userPwd, getRealSalt(formatSalt), ENC_TYPE_MD5, "UTF-8");
        } else {
            encryptPwd = Util.getEncrypt(userPwd);
        }
        return dbPwd.equals(encryptPwd);

    }

    public String getEncryptSm3(String pwd, String salt, String encType, String encoding) {
        try {
            Class aClass = Class.forName("weaver.sm.SM3Utils");
            Method getEncrypt = aClass.getDeclaredMethod("getEncrypt", new Class[]{String.class, String.class, String.class, String.class});
            return (String) getEncrypt.invoke(null, new Object[]{pwd, salt, encType, encoding});
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private static String OLD_SM3_FLAG = ENC_TYPE_SM3 + "#";
    private static String NEW_SM3_FLAG = ENC_TYPE_SM3 + "_new#";

    private boolean isNewSM3Salt(String formatsalt) {
        return (formatsalt != null && !"".equals(formatsalt)) && formatsalt.indexOf(NEW_SM3_FLAG) >= 0;
    }

    private boolean isOldSM3Salt(String formatsalt) {
        return (formatsalt != null && !"".equals(formatsalt)) && formatsalt.indexOf(OLD_SM3_FLAG) >= 0;
    }

    private String getRealSalt(String formatSalt) {
        if (formatSalt == null || "".equals(formatSalt)) return "";
        if (formatSalt.indexOf("#") < 0) return formatSalt;
        return formatSalt.split("#")[1];
    }

    private void writeLog(String val) {
        xssUtil.writeLog(">>second login check >> " + val, true);
    }

    private String replaceStr(String val) {
        if (val == null) return "";
        val = val.replaceAll("_s-s_", "+");
        val = val.replaceAll("_s-1_", "on");
        val = val.replaceAll("_s-2_", "oN");
        val = val.replaceAll("_s-3_", "On");
        val = val.replaceAll("_s-4_", "ON");
        val = val.replaceAll("_s-5_", "=");
        val = val.replaceAll("_s-6_", "0X");
        val = val.replaceAll("_s-7_", "0x");
        val = val.replaceAll("_s-8_", "`");
        val = val.replaceAll("_s-9_", "/");
        val = val.replaceAll("_s-10_", "in");
        val = val.replaceAll("_s-11_", "iN");
        val = val.replaceAll("_s-12_", "In");
        val = val.replaceAll("_s-13_", "IN");

        if (val.endsWith("_check_")) {
            val = val.replaceAll("_check_", "");
        }
        return val;
    }
%>
