登陸 要求 密碼必須包含數字、大寫字母、小寫字母、特殊字字符4種中至少3種

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>修改密碼 | ${appName} - ${sysName}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>${appName}-${sysName}</title> <%include("/admin/header.html"){}%>
<script type="text/javascript">
var app="${app}";
</script>
<link rel="stylesheet" href="${app}assets/css/amazeui-qhyf.css">
</head>
<body>
    <div class="am-g" style="padding-top: 3%;">
        <div class="am-u-lg-3 am-u-md-6 am-u-sm-centered loginContent">
            <div class="loginBox">
                <div class="loginTitle">
                    <div class="inner">
                        <i class="title-icon"></i>
                        <h1>${appName}</h1>
                        <span>首次登錄請先修改密碼</span>
                    </div>
                </div>
                <!-- loginTitle end -->
                <div class="log-mainbox">
                    <form method="post" id="changePasswordForm" class="am-form" 
                        action="${app}password/change">
                        <fieldset>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="user"></i> <input name="userName" type="text"
                                    id="userName" minlength="4" placeholder="請輸入用戶名" required="required" />
                            </div>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="pass"></i> <input name="oldPassword" type="password"
                                    id="oldPassword" minlength="6" onblur="javascrpit:checkPassWord()" placeholder="請輸入原密碼" required/>
                            </div>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="pass"></i> <input name="password" type="password"
                                    id="password" minlength="8"placeholder="請輸入新密碼" required />
                            </div>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="pass"></i> <input name="passwordConfirm" type="password"
                                    id="passwordConfirm" data-equal-to="#password" minlength="8" placeholder="請再次輸入新密碼" required="required" />
                            </div>
                           <div class="am-cf" style="margin-bottom: 30px;">
                                <input id="changePasswordBtn" type="button"
                                    class="am-btn am-btn-primary am-btn-sm am-fl log-sendBox log-sendshadowFont log-sendBoxShadow "
                                    value="修改密碼" />
                            </div>
                            <span style="color:#FFFFFF;font-size: 5px;margin-left: 0px">新密碼必須包含數字、大寫字母、小寫字母、特殊字字符至少3種,長度必須大於或等於8位</span>
                        </fieldset>
                    </form>
                </div>
                <!-- log-mainbox end -->

            </div>
            <div class="loginShadow" style="margin-top: 10px;">
                <img src="${app}assets/i/image/loginShadow.jpg">
            </div>
        </div>
    </div>
    <div class="admin-tpl" id="templateDiv">
    
    <%include("/admin/template/modal.tpl"){}%>
    </div>
    <div id="modal-div"></div>
    <script src="${app}assets/js/jquery.min.js"></script>
    <script src="${app}assets/js/admin/admin.js"></script>
    <script src="${app}assets/js/admin/admin.utils.js"></script>
    <script src="${app}assets/js/amazeui.min.js"></script>
    <script src="${app}assets/js/handlebars.min.js"></script>
    <script type="text/javascript">
     //每一個模塊都應該提供一個init方法用來進行事件註冊什麼的
    function changePasswordAdmin() {
    }// 定義一個類(函數)
    changePasswordAdmin.formId="changePasswordForm";
    changePasswordAdmin.comfirBtnName="肯定";
    changePasswordAdmin.modal=null;
    var $modalTpl = $('#admin-modal-div-tpl');
    var $modalDivName = "#modal-div";
    var $modalDiv = $($modalDivName);
    //爲該類(函數)添加一個靜態方法extend
    changePasswordAdmin.extend = function(obj) {
        for ( var a in obj)
            this[a] = obj[a];
    }    
    changePasswordAdmin.extend({                 
        init : function(data) {
            //註冊新增按鈕
            $("#changePasswordBtn").on(
                    'click',function(){
                        commit;
                    });//新增按鈕註冊結束
            
     },//init End
    commit : function(data) {
            var passwordConfirm = $('#changePasswordForm').find('#passwordConfirm').val();
            var password = $('#changePasswordForm').find('#password')
            .val();
            if (passwordConfirm !== password) {
                alertMsg("初始密碼和確認密碼必須一致");
                return;
            }
             var $form= $("#"+changePasswordAdmin.formId);
             commitForm($form, changePasswordAdmin.modal,changePasswordAdmin);        
             } 
  });//extend  END
    function checkPassWord(){
        var oldPassword = document.getElementById("oldPassword").value;
        var userName= document.getElementById("userName").value;
     /* var para={};
        para['oldPassword']=oldPassword;
        para['userName']=userName; */
        ajax_jsonp("${app}password/check", {"oldPassword":oldPassword,"userName":userName}, function(response){
            if(response.errmsg=="密碼不正確,請從新輸入"){
                alert("密碼不正確請從新輸入");
                //alert("密碼不正確請從新輸入");
                return;
            }
        },null,"POST");
    }
     $("#changePasswordBtn").on(
                'click',
                function() {
                    var passwordConfirm = $('#changePasswordForm').find(
                        '#passwordConfirm').val();
                    var password = $('#changePasswordForm').find('#password').val();
                    if (passwordConfirm !== password) {
                        alert("新密碼和確認密碼必須一致");
                        return false;
                    }
                    if (password == "" || password.length < 8) {
                        alert("密碼至少爲8位");
                        return false;
                    }
                    var passwordFormat = /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\\\W_!@#$%^&*`~()-+=]{8,30}$/
                    if (!passwordFormat.test(password)) {
                        alert("新密碼必須包含數字、大寫字母、小寫字母、特殊字字符4種中至少3種");
                        return;
                    }
                    if (!passwordFormat.test(passwordConfirm)) {
                        alert("確認密碼必須包含數字、大寫字母、小寫字母、特殊字字符4種中至少3種");
                        return;
                    }
                     var $form= $("#"+changePasswordAdmin.formId);
//                      commitForm($form, changePasswordAdmin.modal,changePasswordAdmin);
                        // 異步提交
                    var formData = $form.serializeArray();
                    var data = {};
                    $.each(formData, function(index, object) {
                        data[object.name] = object.value;
                    });    
                    
                    url = build_url("${app}password/change");
                    $.ajax({
                        async: true,
                        data: data,
                        url: url,
                        dataType: "json",
                        type: "POST"
                    }).then(function(data, status) {
                        if(!checkResponseData(data)) {
                            if(data && data.errmsg) {
                                alert(data.errmsg);
                                $("#userName").val("");
                                $("#oldPassword").val("");
                                $("#password").val("");
                                $("#passwordConfirm").val("");
                                return;
                            } else {
                                console.error("發生未知錯誤");
                            }
                        }
                    }, function(data, status, errorThrown) {
                        if(data.status && data.status === 200) {
                            document.write(data.responseText);
                            return;
                        }
                    });
                });
    </script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>登錄 | ${appName} - ${sysName}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>${appName}-${sysName}</title> <%include("/admin/header.html"){}%>
<script>
    if (!endWith(window.location.href, "/login")
            && !endWith(window.location.href, "/login/")) {
        console.log("非登錄地址,從新刷新一次登錄界面");
        window.location.href = "${app}login";
    }
    $(function() {
        var loginMsg = "${loginErrMsg!}";
        if (loginMsg != "") {
            alert(loginMsg);
        }
    });
    $(function() {
        var needPhoneCheck = "${needPhoneCheck!}";
        if (needPhoneCheck) {
            $("#identifyingCode").parent(".iptBox").css('display','block');
            if("1"==needPhoneCheck){
                $("#resend").css('display','block');
                settime($("#resend"));
            }else if("2"==needPhoneCheck){
                $("#resend").css('display','block');
            }
        }
    });
    $(function() {
        var obj = $("#resend");
        var countdown = "${countdown!}";
        settime(obj);
    });
</script>
</head>
<body>
    <div class="am-g" style="padding-top: 3%;">
        <div class="am-u-lg-3 am-u-md-6 am-u-sm-centered loginContent">
            <div class="loginBox">
                <div class="loginTitle">
                    <div class="inner">
                        <i class="title-icon"></i>
                        <h1>${appName}</h1>
                        <span>您好!歡迎進入${appName}!</span>
                    </div>
                </div>
                <!-- loginTitle end -->
                <div class="log-mainbox">
                    <form method="post" class="am-form" action="${app}action/login" id="form">
                        <fieldset>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="user"></i> <input name="userName" type="text"
                                    value="${loginUserId!}" id="userName" minlength="4"
                                    placeholder="用戶名" required />
                                    <input name="mobile" type="hidden"
                                    value="${mobile!}" id="mobile"/>
                                    <input name="countdown" type="hidden"
                                    value="${countdown!}" id="countdown"/>
                            </div>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;">
                                <i class="pass"></i> <input name="password" type="password"
                                    id="password" minlength="6" placeholder="密碼" required />
                            </div>
                            <div class="iptBox ipt-logCon" style="margin-bottom: 30px;display:none; width:158px;">
                                <i class="pass"></i> <input name="identifyingCode" type="text"
                                    id="identifyingCode" minlength="6" placeholder="驗證碼"/>
                            </div>
                            <input type="button" id="resend" value="從新發送"  style="margin-top: -68px;width: 150px;height: 39px;float: right;display: none;border-radius: 5px;background: #E6E6E6;"/> 
                            <div class="am-cf" style="margin-bottom: 30px;">
                                <input type="button"
                                    class="am-btn am-btn-primary am-btn-sm am-fl log-sendBox log-sendshadowFont log-sendBoxShadow " onclick="check()"
                                    value="登   錄" />
                            </div>
                        </fieldset>
                    </form>
                    <!--                     <div class="log-forgetcon"> -->
                    <!--                         <a href="javascript:void(0);" class="log-forget"> <i></i> -->
                    <!--                             忘記密碼? -->
                    <!--                         </a> -->
                    <!--                     </div> -->
                </div>
                <!-- log-mainbox end -->

            </div>
            <div class="loginShadow" style="margin-top: 10px;">
                <img src="${app}assets/i/image/loginShadow.jpg">
            </div>
        </div>
    </div>

</body>
<script src="${app}assets/js/admin/admin.js"></script>
<script type="text/javascript">
    if($("#countdown").val()!=""){
        var countdown=$("#countdown").val();
    }else{
        var countdown=120; 
    }
    $("#resend").on("click",function(){
        var obj = $("#resend");
        resend();
        settime(obj);
    })
    function settime(obj) { //發送驗證碼倒計時
        if (countdown == 0) { 
            obj.attr('disabled',false);  
            obj.val("獲取驗證碼");
            $("#resend").css("background","#E6E6E6");
            $("#countdown").val("120");
            countdown = 120; 
            return;
        } else { 
            obj.attr('disabled',true);
            obj.val("(" + countdown + ")S");
            $("#countdown").val(""+ countdown +"");
            countdown--; 
        } 
    setTimeout(function() { 
        settime(obj) }
        ,1000) 
    }
    function resend(){    
        $("#countdown").val("120");
        $.ajax({
             type: "POST",
             url: "/action/login/",
             data: {"mobile" : $("#mobile").val(),"flag":"1"},
             dataType: "json",
             success: function(data){}
         });
    }
    function check() {
        var passwordFormat = /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\\\W_!@#$%^&*`~()-+=]{8,30}$/
        var commitFlag = false
        if ($("#password").val().length < 8||!passwordFormat.test($("#password").val())) {
            commitFlag = alertMsg("密碼必須包含數字、大寫字母、小寫字母、特殊字字符至少3種,長度必須大於或等於8位.是否修改",'COMFIR');
            if(commitFlag){
                document.getElementById('form').submit();
            }
        } else {              88888888
            document.getElementById('form').submit(); //驗證成功進行表單提交
        }
    }
</script>
</html>
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyuncs.exceptions.ClientException;
import com.google.common.io.BaseEncoding;
import com.jfinal.core.ActionKey;
import com.jfinal.core.action.Rest;
import com.jfinal.core.pojo.RestMethod;
import com.qhyf.app.bl.BlConfig;
import com.qhyf.app.bl.BlConstant;
import com.qhyf.app.bl.base.common.AdminService;
import com.qhyf.app.bl.base.common.EnvironmentUtils;
import com.qhyf.app.bl.base.support.SuppliersToken;
import com.qhyf.app.bl.base.util.SmsUtils;
import com.qhyf.app.bl.base.util.VerifyCodeUtil;
import com.qhyf.app.bl.model.SysUser;
import club.newepoch.persistent.db.common.Db;
import club.newepoch.persistent.db.exception.ActiveRecordException;
import club.newepoch.persistent.db.pojo.Record;
import club.newepoch.utils.AssertUtils;



public class LoginController extends QhyfController {

    /**
     * 日誌
     */
    private static  Logger logger = LoggerFactory.getLogger(LoginController.class);

    /**
     * 篩選用戶
     */
    private static String selectUser = "SELECT * FROM `sys_user` WHERE `sys_status`=? AND `user_id`=?";

    /**
     * 註銷
     */
    @ActionKey("/logout")
    public void logout() {
        Record loginUser = AdminService.getLoginUser(this);
        if (loginUser != null) {
            AdminService.logout(this, loginUser);
        } else {
            redirect("/");
        }
    }

    /**
     * 打開登錄界面
     */
    public void index() {
//        String nesid = AdminService.getNesid(this);
//        if (!StringUtils.isBlank(nesid)) {
//            Record user = AdminService.getLoginUser(this);
//            if (AdminService.isValidSession(nesid, user)) {
//                // 已登錄,直接跳轉到主界面
//                logger.info("用戶[{}]已登錄(nesid=[{}],直接跳轉到登錄界面", user.getStr(BlConstant.FIELD_USER_ID), nesid);
//                redirect("/admin/");
//                return;
//            }
//        }
        render("/admin/login.html");
    }

    /**
     * 修改密碼
     */
    @Rest(method = RestMethod.GET)
    @ActionKey("/password/change")
    public void changePassword() {
        this.render("/admin/changePassword.html");
    }
    
    /**
     * 修改密碼
     */
    @Rest(method = RestMethod.POST)
    @ActionKey("/password/change")
    public void doChangePassword() {
        Record loginUser = null;
        try {
            String userName = this.getPara("userName");
            AssertUtils.notBlank(userName, "用戶名不能爲空");
            String oldPassword = this.getPara("oldPassword");
            AssertUtils.notBlank(oldPassword, "登錄密碼不能爲空");
            String password = this.getPara("password");
            AssertUtils.notBlank(password, "新密碼不能爲空");
            String passwordConfirm = this.getPara("passwordConfirm");
            AssertUtils.notBlank(passwordConfirm, "確認密碼不能爲空");
            AssertUtils.isTrue(password.equals(passwordConfirm), "新密碼和確認密碼必須一致");
            String sql = selectUser;
            loginUser = Db.findFirst(sql, BlConstant.SYS_STATUS_VALUE, userName);
            AssertUtils.notNull(loginUser, "登錄帳號不存在或密碼錯誤");
            this.checkPassword(loginUser, userName, oldPassword);
            String newPasswordMd5 = AdminService.getUserPassword(loginUser.getStr(BlConstant.FIELD_SALT),
                    passwordConfirm);
            Db.update("update " + SysUser.dao.getTable().getName() + " set status='1',password=? where uuid=?",
                    newPasswordMd5, loginUser.getStr(BlConstant.FIELD_UUID));
            loginUser.set("password", newPasswordMd5);
            AdminService.login(this, loginUser);
            // this.renderVjson("密碼修改爲功");
            // redirect("/admin/");
            logger.debug("密碼修改爲功,跳轉到後臺界面");
//bug對應NO.1455---修改完成後界面不跳轉 add by dujiang 2016/08/25 start
            render("/admin/login.html");
//            this.redirect(EnvironmentUtils.me().getEnv().getLoginAction());
//bug對應NO.1455---修改完成後界面不跳轉 add by dujiang 2016/08/25 end
        } catch (Exception e) {
            logger.error("修改密碼失敗", e);
//            this.renderVjson("修改密碼失敗");
            this.renderVerrorJson(2, e.getLocalizedMessage(), e);
        }
    }

    /**
     * 檢驗密碼
     * 
     * @throws ActiveRecordException
     */
    @Rest(method = RestMethod.POST)
    @ActionKey("/password/check")
    public void checkPassword() {
        Record loginUser = null;
        String userName = this.getPara("userName");
        AssertUtils.notBlank(userName, "請先輸入用戶名");
        String oldPassword = this.getPara("oldPassword");
        AssertUtils.notBlank(oldPassword, "密碼不能爲空");
        String sql = selectUser;
        try {
            loginUser = Db.findFirst(sql, BlConstant.SYS_STATUS_VALUE, userName);
            AssertUtils.notNull(loginUser, "用戶不存在");
            this.checkPassword(loginUser, userName, oldPassword);
            if (loginUser != null) {
                this.renderVjson("密碼正確,請繼續執行");
            } else {
                logger.error("密碼不正確,請從新輸入");
                this.renderVjson("密碼不正確,請從新輸入");
            }
        } catch (Exception e) {
            logger.error("密碼不正確,請從新輸入", e);
            this.renderVjson("密碼不正確,請從新輸入");
        }
    }

    /**
     * 登錄(登錄必須以post方式)
     */
    @Rest(method = RestMethod.POST)
    @ActionKey("/action/login")
    public void loginAction() {
        String mobile = this.getPara("mobile");
        String flag = this.getPara("flag");//是不是從新發送的消息
        String countdown = this.getPara("countdown");
        if("1".equals(flag)){
            resend(mobile);
        }else{
            String userName = this.getPara("userName");
            try {
                Record loginUser = null;
                AssertUtils.notBlank(userName, "登錄帳號不能爲空");
                String password = this.getPara("password");
                AssertUtils.notBlank(password, "登錄密碼不能爲空");
                String identifyingCode = this.getPara("identifyingCode");
                String sql = selectUser;
                loginUser = Db.findFirst(sql, BlConstant.SYS_STATUS_VALUE, userName);
                if (loginUser != null) {
                    String status = loginUser.getStr("status");
                    AssertUtils.notBlank(status, "帳戶異常,請聯繫管理員");
                    if ("0".equals(status)) {
                        this.setAttr("userName", userName);
                        this.redirect("/admin/changePassword.html");
                        return;
                    }
                    String passwordFormat = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\\\W_!@#$%^&*`~()-+=]{8,30}$";
                    Pattern pattern=Pattern.compile(passwordFormat);
                    Matcher matcher=pattern.matcher(password);                                  
                    if(password.length()<8||!matcher.matches()){
                        String securityPass = AdminService.getUserPassword(loginUser.getStr(BlConstant.FIELD_SALT), password);
                        AssertUtils.isTrue(loginUser.getStr("password").equals(securityPass),"密碼輸入不正確,請從新輸入");
                        this.redirect("/admin/changePassword.html");
                        return;
                    }
                    AssertUtils.isTrue(!"2".equals(status), "帳戶已被鎖定");
                }
                if (BlConfig.DEV) {
                    if (loginUser == null) {
                        loginUser = new Record();
                        loginUser.set("userName", "測試用戶");
                        loginUser.set(BlConstant.FIELD_UUID, userName);
                        loginUser.set(BlConstant.FIELD_USER_ID, userName);
                        loginUser.set(BlConstant.FIELD_CORDYS_USER_ID, userName);
                        loginUser.set(BlConstant.FIELD_EXPIRE_TIME, Long.MAX_VALUE);// 測試超時時間爲最長
                        loginUser.set(BlConstant.FIELD_CORDYS_USER_ID, userName);
                    }
                } else {
                    AssertUtils.notNull(loginUser, "登錄帳號不存在或密碼錯誤");
                    this.checkPassword(loginUser, userName, password);
                    if(EnvironmentUtils.me().getEnv().isWhiteListOnOff()){
                        // 判斷條件
                        boolean conditions = StringUtils.isBlank(identifyingCode) && !checkIp();
                        // 若是是供應商或項目公司人員則不須要白名單限制
                        if(AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1024") 
                                || AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1050")
                                || AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1026")
                                || AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1052")
                                || AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1051")){
                            conditions = StringUtils.isBlank(identifyingCode) && false;
                        }
                        if(conditions){
                            mobile = loginUser.getStr("mobile");
                            AssertUtils.notBlank(mobile, "您不在辦公區域且預留手機號碼爲空,不能登陸系統");
                            String code =VerifyCodeUtil.getRandNum();
                            SmsUtils.sendSms(mobile, code);
                            
                            this.setAttr("mobile", mobile);
                            this.setAttr("needPhoneCheck", "1");
                            AssertUtils.isTrue(false, "您的訪問ip未在系統白名單呢,請用手機驗證的方式登陸");
                        }else if(StringUtils.isNotBlank(identifyingCode)){
                            mobile = loginUser.getStr("mobile");
                            String content = SmsUtils.querySendDetails(mobile, "").getSmsSendDetailDTOs().get(0).getContent();
                            String regex = "\\d*";
                            Pattern p = Pattern.compile(regex);
                            Matcher m = p.matcher(content);
                            while (m.find()) {
                                if (!"".equals(m.group())){
                                    this.setAttr("mobile", mobile);
                                    this.setAttr("needPhoneCheck", "2");
                                    this.setAttr("countdown", countdown);
                                    AssertUtils.isTrue(identifyingCode.equals(m.group()), "驗證碼錯誤");
                                }
                            }
                        }
                    }
                    loginUser.set(BlConstant.FIELD_EXPIRE_TIME, this.getQhyfService().getEnv().getLoginExpireTime());
                }
                //跨域登陸,若是供應商在qhyf-bl服務器上登陸,將自動跳轉到供應商服務器,並登陸
                //1.先發送token給供應商服務器,並保存緩存
                //2.再帶有token參數響應重定向到供應商服務器
                //3.供應商服務器根據token從緩存獲取到用戶信息,並登陸
                //4.刪除供應商服務器的緩存,避免其餘地方使用相同的url登陸
                if(AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1024")){
                    SuppliersToken sToken  = new SuppliersToken(loginUser);
                    sToken.postToken(EnvironmentUtils.me().getEnv().getSuppliersAddress() + "/admin/suppliersToken/");
                    redirect(EnvironmentUtils.me().getEnv().getSuppliersAddress() + "/admin/" + "?suppliersToken=" + sToken.getToken());
                    return;
                }
                if (AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1051")) {
                    SuppliersToken sToken  = new SuppliersToken(loginUser);
                    sToken.postToken(EnvironmentUtils.me().getEnv().getSuppliersAddress() + "/admin/suppliersToken/");
                    redirect(EnvironmentUtils.me().getEnv().getSuppliersAddress() + "/cfcaui/suppliersDocumentSeal.html" + "?suppliersToken=" + sToken.getToken());
                    return;
                }
                // 跨域登陸,若是項目公司在qhyf-bl服務器上登陸,將自動跳轉到項目公司服務器,並登陸
                if (AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1050")
                        || AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1026")) {
                    SuppliersToken xToken  = new SuppliersToken(loginUser); // SuppliersToken在此處能夠通用
                    xToken.postToken(EnvironmentUtils.me().getEnv().getXmgsAddress() + "/admin/suppliersToken/");
                    redirect(EnvironmentUtils.me().getEnv().getXmgsAddress() + "/admin/" + "?suppliersToken=" + xToken.getToken());
                    return;
                }
                if (AdminService.checkRole(loginUser.getStr("uuid"), "qhyf1052")) {
                    SuppliersToken sToken  = new SuppliersToken(loginUser);
                    sToken.postToken(EnvironmentUtils.me().getEnv().getXmgsAddress() + "/admin/suppliersToken/");
                    redirect(EnvironmentUtils.me().getEnv().getXmgsAddress() + "/cfcaui/itemDocumentSeal.html" + "?suppliersToken=" + sToken.getToken());
                    return;
                }
                String nesid = AdminService.login(this, loginUser);
                redirect("/admin/?token=" + nesid);
            } catch (Exception e) {
                logger.error("登陸失敗", e);
                this.setAttr("loginUserId", userName);
                this.setAttr("loginErrMsg", e.getMessage());
                this.render("/admin/login.html");
                // this.renderVerrorJson(1, e.getLocalizedMessage());
            }
        }
        
    }
    
    /**
     * 獲取Token
     * @return
     */
    @Rest(method = RestMethod.POST)
    @ActionKey("/action/getToken")
    public void getToken() {
        int errcode = 0;
        String errmsg= "";
        Map<String,Object> token=new HashMap<String,Object>();
        long expireTime = EnvironmentUtils.me().getEnv().getLoginExpireTime();
        String userName = this.getPara("userName");
        if(StringUtils.isBlank(userName)){
            errcode = 1001;
            errmsg = "用戶名不能爲空";    
        }else{
            String password = this.getPara("password");
            if(StringUtils.isBlank(password)){
                errcode = 1002;
                errmsg = "密碼不能爲空";
            }else{
                try {
                    Record loginUser = Db.findFirst(selectUser, BlConstant.SYS_STATUS_VALUE, userName);
                    if (loginUser != null) {
                        String status = loginUser.getStr("status");
                        if(StringUtils.isBlank(status)){
                            errcode = 1003;
                            errmsg = "帳戶異常";
                        }else if ("0".equals(status)) {
                            errcode = 1004;
                            errmsg = "帳戶未經過驗證";                    
                        }else if("2".equals(status)){
                            errcode = 1005;
                            errmsg = "帳戶已被鎖定";    
                        }else if("1".equals(status)  ){
                            this.checkPassword(loginUser, userName, password);
                            String nesid = AdminService.login(this, loginUser);
                            token.put("token", nesid);
                            token.put("expire", expireTime);
                        }
                    }else{
                        errcode = 1006;
                        errmsg = "登錄帳號不存在或密碼錯誤";
                    }
                    
                } catch (Exception e) {
                    logger.error("登錄處理異常:"+e.getMessage(),e);
                    errcode = 9999;
                    errmsg = "登錄處理異常:"+e.getMessage();
                }
            }
        }
        this.renderVerrorJson(errcode, errmsg, token);
    }

    /**
     * 修改密碼
     * 
     * @param loginUser
     *            登錄用戶
     * @param loginUserName
     *            登錄用戶名(郵箱、手機、id)
     * @param password
     *            密碼
     * @return 密文
     */
    private String checkPassword(Record loginUser, String loginUserName, String password) {
        String salt = loginUser.getStr(BlConstant.FIELD_SALT);
        if (StringUtils.isBlank(salt)) {
            salt = this.getQhyfService().getEnv().getSalt();
            logger.debug("用戶[%s]未設置[salt],使用環境變量值[%s]", loginUserName, salt);
        }
        String passwordMd5 = loginUser.getStr("password");
        String securityPass = AdminService.getUserPassword(salt, password);
        if (BlConfig.DEV) {
            logger.error("原密碼爲:[{}],salt:[{}]", password, salt);
        }
        AssertUtils.isTrue(securityPass.equals(passwordMd5), "密碼錯誤");
        return securityPass;
    }
    
    /**
     * 白名單校驗
     * @return
     * @throws ActiveRecordException 
     */
    private Boolean checkIp () throws Exception{
        
        HttpServletRequest request = this.getRequest();
        String hostIp = getV4IP(request);
        logger.info("客戶端外網IP爲:[{}]", hostIp);
        Record ip = Db.findFirst("SELECT * FROM `biz_ip_white_list` WHERE `status`=? AND `ip`=?", BlConstant.SYS_STATUS_VALUE, hostIp);
        if(ip!=null){
            logger.info("庫中IP爲:[{}]", ip.getStr("ip"));
            return true;
        }else{
            return false;
        }
    }

    /**
     * 獲取客戶端外網IP地址 
     * @return
     */
    private String getV4IP(HttpServletRequest request) throws Exception{
        String forwarded  = request.getHeader("X-Forwarded-For");
        logger.info("X-Forwarded-For爲:[{}]", forwarded);
        String realip = request.getHeader("X-Real-IP");
        logger.info("X-Real-IP爲:[{}]", realip);
        String ip ="";
        //非代理服務器的狀況
        if(StringUtils.isEmpty(forwarded)&&StringUtils.isEmpty(realip)){
            String chinaz = "http://ip.chinaz.com";
            StringBuilder inputLine = new StringBuilder();
            String read = "";
            URL url = null;
            HttpURLConnection urlConnection = null;
            BufferedReader in = null;
            url = new URL(chinaz);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedReader( new InputStreamReader(urlConnection.getInputStream(),"UTF-8"));
            while((read=in.readLine())!=null){
                inputLine.append(read+"\r\n");
            }
            if(in!=null){
                in.close();
            }
            Pattern p = Pattern.compile("\\<dd class\\=\"fz24\">(.*?)\\<\\/dd>");
            Matcher m = p.matcher(inputLine.toString());
            if(m.find()){
                String ipstr = m.group(1);
                ip = ipstr;
            }
        }else{
            if(forwarded != null && (!"unknown".equalsIgnoreCase(forwarded))){
                ip = forwarded;
            }
            if(forwarded == null || forwarded.length() == 0 || "unknown".equalsIgnoreCase(forwarded)){
                ip = realip;
            }
            if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
                ip = request.getRemoteAddr();  
                if(ip.equals("127.0.0.1") || ip.equals("0:0:0:0:0:0:0:1")){  
                    //根據網卡取本機配置的IP  
                    InetAddress inet=null;  
                    try {  
                        inet = InetAddress.getLocalHost();  
                    } catch (UnknownHostException e) {  
                        e.printStackTrace();  
                    }  
                    ip= inet.getHostAddress();  
                }  
            }  
            //對於經過多個代理的狀況,第一個IP爲客戶端真實IP,多個IP按照','分割  
            if(ip!=null && ip.length()>15){ //"***.***.***.***".length() = 15  
                if(ip.indexOf(",")>0){  
                    ip = ip.substring(0,ip.indexOf(","));  
                }  
            }  
        }
        return ip;
    }
    
    /**
     * 從新發送手機驗證信息
     */
    private void resend(String mobile) {
        try {
            Integer totalCount = Integer.valueOf(SmsUtils.querySendDetails(mobile, "").getTotalCount());
            if(totalCount<10){
                String code =VerifyCodeUtil.getRandNum();
                SmsUtils.sendSms(mobile, code);    
                this.setAttr("mobile", mobile);
                this.setAttr("needPhoneCheck", "2");
                AssertUtils.isTrue(false, "已從新發送,請查收");
            }else{
                AssertUtils.isTrue(false, "今日您已用手機驗證多達十次以上,請明天再嘗試登陸");
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }    
}
相關文章
相關標籤/搜索