使用BootstrapValidator进行注册校验和登录错误提示

1、介绍


在AdminEAP框架中,使用了BootstrapValidator校验框架,本文以注册校验的用户名、登录名、密码、确认密码的校验(后面还有时间区间、服务器校验)为例,讲述BootstrapValidator的使用。同时以登录错误提示为例,说明如何在动态改变组件的错误提示信息。

先看下面的注册与登录的校验效果图:

注册校验

注册校验

登录错误提示:根据不同的错误类型,动态改变组件的样式和错误提示内容

账号问题

密码问题

2、注册校验


1、头部引入bootstrap-validator.css

<link rel="stylesheet"
          href="${basePath}/resources/adminlte/plugins/bootstrap-validator/dist/css/bootstrap-validator.css"/>

${basePath}为系统的路径变量

2、form组件

 <form action="${basePath}/oauth/register" method="post" id="register-form">
            <input type="hidden" name="oAuthId" value="${oAuthInfo.oAuthId?default('-1')}">
            <input type="hidden" name="oAuthType" value="${oAuthInfo.oAuthType?default('-1')}">
            <div class="form-group has-feedback">
                <input type="text" class="form-control" name="userName" id="userName" placeholder="请输入用户名" required>
                <span class="glyphicon glyphicon-user form-control-feedback"></span>
            </div>
            <div class="form-group has-feedback">
                <input type="text" class="form-control" name="loginName" id="loginName" placeholder="请输入登录邮箱/登录名">
                <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
            </div>
            <div class="form-group has-feedback">
                <input type="password" class="form-control" name="password" id="password" placeholder="请输入密码">
                <span class="glyphicon glyphicon-lock form-control-feedback"></span>
            </div>
            <div class="form-group has-feedback">
                <input type="password" class="form-control" name="repassword" id="repassword" placeholder="再次确认密码">
                <span class="glyphicon glyphicon-log-in form-control-feedback"></span>
            </div>
            <div class="row">
                <div class="col-xs-12">
                    <div class="checkbox icheck">
                        <label>
                            <input type="checkbox" name="rememberMe" required> 同意遵循<a href="#">AdminEAP协议</a>
                        </label>
                    </div>
                </div>
                <!-- /.col -->
            </div>
            <div class="row">
                <div class="col-xs-12">
                    <button type="submit" class="btn btn-danger btn-block btn-flat">注 册</button>
                </div>
            </div>
        </form>

3、引入bootstrap-validator.js

<script src="${basePath}/resources/adminlte/bootstrap/js/bootstrap.min.js"></script>

4、校验的核心js代码

<script>
    $(function () {
        //将checkbox渲染为icheck样式
        $('input').iCheck({
            checkboxClass: 'icheckbox_square-red',
            radioClass: 'iradio_square-red',
            increaseArea: '20%' // optional
        });

        //此处为校验的核心代码
        $("#register-form").bootstrapValidator({
            submitHandler: function (valiadtor, loginForm, submitButton) {

                valiadtor.defaultSubmit();
            },
            fields: {
                userName: {
                    validators: {
                        notEmpty: {
                            message: '用户名不能为空'
                        },
                        stringLength: {
                            /*长度提示*/
                            min: 4,
                            max: 30,
                            message: '用户名长度必须在4到30之间'
                        }
                    }
                },
                loginName: {
                    validators: {
                        notEmpty: {
                            message: '登录邮箱名或用户名不能为空'
                        },
                        stringLength: {
                            /*长度提示*/
                            min: 4,
                            max: 30,
                            message: '用户名长度必须在4到30之间'
                        },
                        threshold: 4,//只有4个字符以上才发送ajax请求
                        remote: {
                            url: "${basePath}/oauth/checkUnique",
                            data: function (validator) {
                                return {
                                    loginName: $("#loginName").val(),
                                    userId: null
                                };
                            },
                            message: '该登录名已被使用,请使用其他登录名',
                            delay:2000
                        }
                    }
                },
                password: {
                    validators: {
                        notEmpty: {
                            message: '密码不能为空'
                        },
                        stringLength: {
                            /*长度提示*/
                            min: 6,
                            max: 30,
                            message: '密码长度必须在6到30之间'
                        },
                        different: {//不能和用户名相同
                            field: 'loginName',//需要进行比较的input name值
                            message: '不能和用户名相同'
                        },
                        regexp: {
                            regexp: /^[a-zA-Z0-9_\.]+$/,
                            message: '密码由数字字母下划线和.组成'
                        }
                    }
                },
                repassword: {
                    message: '密码无效',
                    validators: {
                        notEmpty: {
                            message: '密码不能为空'
                        },
                        stringLength: {
                            min: 6,
                            max: 30,
                            message: '用户名长度必须在6到30之间'
                        },
                        identical: {//相同
                            field: 'password',
                            message: '两次密码不一致'
                        },
                        different: {//不能和用户名相同
                            field: 'loginName',
                            message: '不能和用户名相同'
                        },
                        regexp: {//匹配规则
                            regexp: /^[a-zA-Z0-9_\.]+$/,
                            message: '密码由数字字母下划线和.组成'
                        }
                    }
                }

            }
        });

    });

5、登录名唯一性校验的后台代码

 /**
     * 校验当前登录名/邮箱的唯一性
     * @param loginName 登录名
     * @param userId 用户ID(用户已经存在,即又改回原来的名字还是唯一的)
     * @return
     */
    @RequestMapping(value = "/oauth/checkUnique", method = RequestMethod.POST)
    @ResponseBody
    public Map checkExist(String loginName, String userId) {
        Map<String, Boolean> map = new HashMap<String, Boolean>();
        User user = userService.getUserByLoginName(loginName);
        //用户不存在,校验有效
        if (user == null) {
            map.put("valid", true);
        } else {
            //用户存在(存在的用户是当前用户,登录名一致,校验通过,否则校验不通过)
            if(!StrUtil.isEmpty(userId)&&userId.equals(user.getLoginName())){
                map.put("valid",true);
            }else {
                map.put("valid", false);
            }
        }
        return map;
    }

以上的配置完成了注册文本框的各种校验,更多的校验内容,可以查看相关的bootstrap-validator的API文档。

3、登录错误动态提示


1、在后台登录时,会抛出各种登录不成功的提示,需要动态改变前端组件的错误提示信息。不同类型的错误信息编码,要控制不同的组件样式和提示内容。以下是后台抛出的错误类型和错误信息(使用shiro认证)。

  try {
            subject.login(token);
            //通过认证
            if (subject.isAuthenticated()) {
                Set<String> roles = roleService.getRoleCodeSet(userName);
                if (!roles.isEmpty()) {
                    subject.getSession().setAttribute("isAuthorized", true);
                    return MAIN_PAGE;
                } else {//没有授权
                    msg = "您没有得到相应的授权!";
                    model.addAttribute("message", new ResultCode("1", msg));
                    subject.getSession().setAttribute("isAuthorized", false);
                    LOGGER.error(msg);
                    return LOGIN_PAGE;
                }

            } else {
                return LOGIN_PAGE;
            }
            //0 未授权 1 账号问题 2 密码错误  3 账号密码错误
        } catch (IncorrectCredentialsException e) {
            msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect";
            model.addAttribute("message", new ResultCode("2", msg));
            LOGGER.error(msg);
        } catch (ExcessiveAttemptsException e) {
            msg = "登录失败次数过多";
            model.addAttribute("message", new ResultCode("3", msg));
            LOGGER.error(msg);
        } catch (LockedAccountException e) {
            msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";
            model.addAttribute("message", new ResultCode("1", msg));
            LOGGER.error(msg);
        } catch (DisabledAccountException e) {
            msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";
            model.addAttribute("message", new ResultCode("1", msg));
            LOGGER.error(msg);
        } catch (ExpiredCredentialsException e) {
            msg = "帐号已过期. the account for username " + token.getPrincipal() + "  was expired.";
            model.addAttribute("message", new ResultCode("1", msg));
            LOGGER.error(msg);
        } catch (UnknownAccountException e) {
            msg = "帐号不存在. There is no user with username of " + token.getPrincipal();
            model.addAttribute("message", new ResultCode("1", msg));
            LOGGER.error(msg);
        } catch (UnauthorizedException e) {
            msg = "您没有得到相应的授权!" + e.getMessage();
            model.addAttribute("message", new ResultCode("1", msg));
            LOGGER.error(msg);
        }

2、前端核心JS代码

<script>
        $(function () {
            $('input').iCheck({
                checkboxClass: 'icheckbox_square-red',
                radioClass: 'iradio_square-red',
                increaseArea: '20%' // optional
            });

            fillbackLoginForm();
            $("#login-form").bootstrapValidator({
                message:'请输入用户名/密码',
                submitHandler:function (valiadtor,loginForm,submitButton) {
                    rememberMe($("input[name='rememberMe']").is(":checked"));
                    valiadtor.defaultSubmit();
                },
                fields:{
                    userName:{
                        validators:{
                            notEmpty:{
                                message:'登录邮箱名或用户名不能为空'
                            }
                        }
                    },
                    password:{
                        validators:{
                            notEmpty:{
                                message:'密码不能为空'
                            }
                        }
                    }
                }
            });
            <!--freemark语法,查看是否从后台传送过来错误信息,并初始化错误提示组件LoginValidator-->
            <#if message??>
                new LoginValidator({
                    code:"${message.code?default('-1')}",
                    message:"${message.message?default('')}",
                    userName:'userName',
                    password:'password'
                });
            </#if>
        });

        //使用本地缓存记住用户名密码
        function rememberMe(rm_flag){
            //remember me
            if(rm_flag){
                 localStorage.userName=$("input[name='userName']").val();
                 localStorage.password=$("input[name='password']").val();
                localStorage.rememberMe=1;
            }
            //delete remember msg
            else{
                localStorage.userName=null;
                localStorage.password=null;
                localStorage.rememberMe=0;
            }
        }

        //记住回填
        function fillbackLoginForm(){
            if(localStorage.rememberMe&&localStorage.rememberMe=="1"){
                $("input[name='userName']").val(localStorage.userName);
                $("input[name='password']").val(localStorage.password);
                $("input[name='rememberMe']").iCheck('check');
                $("input[name='rememberMe']").iCheck('update');
            }
        }
    </script>

3、LoginValidator组件的代码 login.js

/**
 * Created by billJiang on 2017/1/12.
 * 登录异常信息显示
 */

function LoginValidator(config) {
    this.code = config.code;
    this.message = config.message;
    this.userName = config.userName;
    this.password = config.password;
    this.initValidator();
}

//0 未授权 1 账号问题 2 密码错误  3 账号密码错误
LoginValidator.prototype.initValidator = function () {
    if (!this.code)
        return;
    if(this.code==0){
       this.addPasswordErrorMsg();
    }else if(this.code==1){
        this.addUserNameErrorStyle();
        this.addUserNameErrorMsg();
    }else if(this.code==2){
        this.addPasswordErrorStyle();
        this.addPasswordErrorMsg();
    }else if(this.code==3){
        this.addUserNameErrorStyle();
        this.addPasswordErrorStyle();
        this.addPasswordErrorMsg();
    }
    return;
}

LoginValidator.prototype.addUserNameErrorStyle = function () {
    this.addErrorStyle(this.userName);
}

LoginValidator.prototype.addPasswordErrorStyle = function () {
    this.addErrorStyle(this.password);
}

LoginValidator.prototype.addUserNameErrorMsg = function () {
    this.addErrorMsg(this.userName);
}

LoginValidator.prototype.addPasswordErrorMsg = function () {
    this.addErrorMsg(this.password);
}


LoginValidator.prototype.addErrorMsg=function(field){
    $("input[name='"+field+"']").parent().append('<small  data-bv-validator="notEmpty" data-bv-validator-for="'+field+'" class="help-block">' + this.message + '</small>');
}

LoginValidator.prototype.addErrorStyle=function(field){
    $("input[name='" + field + "']").parent().addClass("has-error");
}

以上把错误提示封装成了一个LoginValidator组件,方便前端调用,增强代码的可维护性,因为没有找到Bootstrap-validator改变错误提示的接口,所以查看了源码之后做了封装。

4、补充


1、时间区间校验

 "startTime":{
                    validators:{
                        date:{
                            format:'YYYY-MM-DD HH:mm',
                            message:'日期格式不正确'
                        },
                        callback:{
                            callback:function(value,validator){
                                var startTime=value;
                                var endTime=$("#endTime").val();
                                if(startTime&&endTime){
                                    return DateDiff(endTime,startTime)>0;
                                }else{
                                    return true;
                                }

                            },
                            message:'结束时间不能小于开始时间'
                        }
                    }
                },
                "endTime":{
                    validators:{
                        date:{
                            format:'YYYY-MM-DD HH:mm',
                            message:'日期格式不正确'
                        },
                        callback:{
                            callback:function(value,validator){
                                var startTime=$("#startTime").val();
                                var endTime=value;
                                if(startTime&&endTime){
                                    return DateDiff(endTime,startTime)>0;
                                }else{
                                    return true;
                                }

                            },
                            message:'结束时间不能小于开始时间'
                        }

                    }
                },

2、服务器校验

"jobClass": {
        validators: {
               notEmpty: {message: '执行类名不能为空'},
               remote:{
                   url:basePath+"/job/checkJobClass",
                   data: function(validator) {
                       return {
                           jobClass:$('#jobClass').val(),
                       };
                   },
                   message:'该执行类不存在'
               }
           }
       }

后台代码

 @RequestMapping(value="/checkJobClass",method = RequestMethod.POST)
    @ResponseBody
    public Map checkJobClass(String jobClass){
        Map map=new HashMap<>();
        try {
            Class<?> objClass = Class.forName(jobClass);
            if(objClass!=null)
            map.put("valid", true);
            return map;
        } catch (Exception ex) {
            logger.error(ex.getMessage().toString());
            map.put("valid", false);
            return map;
        }
    }

作者:推敲(billjiang)

CSDNblog.csdn.net/jrn1012
Githubhttps://github.com/bill1012
AdminEAPhttp://www.admineap.com
Email:475572229@qq.com

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值