BootstrapValidator实现注册校验和登录错误提示效果

作者:推敲 时间:2024-04-08 10:57:03 

使用BootstrapValidator进行注册校验和登录错误提示,具体内容如下

1、介绍

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

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

注册校验:

BootstrapValidator实现注册校验和登录错误提示效果

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

BootstrapValidator实现注册校验和登录错误提示效果

BootstrapValidator实现注册校验和登录错误提示效果

2、注册校验

1、头部引入bootstrap-validator.css

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


${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="#" rel="external nofollow" >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;
   }
 }

Github: https://github.com/bill1012
AdminEAP:http://www.admineap.com

标签:bootstrap,validator,注册,登录
0
投稿

猜你喜欢

  • 利用二进制文件安装etcd的教程详解

    2023-07-22 00:23:47
  • 微信小程序audio组件在ios端无法播放的解决办法

    2024-04-18 09:47:26
  • MySQL索引下推详细

    2024-01-18 10:01:07
  • 纯CSS3透明水晶盒

    2011-08-24 20:20:06
  • shp2sqlserver 用法简析

    2024-01-17 10:37:23
  • Python 文本文件与csv文件的读取与写入

    2021-02-10 09:57:56
  • 详解 Go 语言中 Map 类型和 Slice 类型的传递

    2024-05-29 22:07:11
  • vue-cli4.5.x快速搭建项目

    2024-04-27 15:52:18
  • Python利用WMI实现ping命令的例子

    2022-07-12 04:42:22
  • pandas的Series类型与基本操作详解

    2021-03-23 12:06:36
  • 详解mysql 组合查询

    2024-01-20 10:43:06
  • MySQL如何让一个表中可以有多个自增列

    2024-01-15 03:41:07
  • Python3创建Django项目的几种方法(3种)

    2021-12-28 00:41:44
  • Symfony核心类概述

    2023-11-17 13:59:48
  • Python 机器学习之线性回归详解分析

    2023-08-12 09:48:13
  • ThinkPHP结合AjaxFileUploader实现无刷新文件上传的方法

    2024-04-17 10:39:54
  • Python绘图示例程序中的几个语法糖果你知道吗

    2021-01-18 17:15:25
  • (X)HTML Strict 下的嵌套规则

    2008-03-08 18:39:00
  • PHP ob缓存以及ob函数原理实例解析

    2023-11-18 17:36:14
  • PDO::errorInfo讲解

    2023-06-06 01:51:53
  • asp之家 网络编程 m.aspxhome.com