基于登录注册用ajax实现手机验证码功能
这几天做的项目接触到了用手机验证码完成一些功能,例如登录、注册、以及修改手机号码,想把流程总结出来分享给大家
基于登录发送
操作 | 手机号 |
---|---|
登录 | 非空、格式正确、已注册 |
先用ajax获取框输入的手机号码提交到controller处理,部分jsp代码如下
<input type="hidden" id="u-name-reg-first" value="0" /><!--第一次输入的号码--> <input type="text" name="key" placeholder="手机号" value=''/> <a type="button" onclick="sendPhoneCodelogin()" titlelogin="登陆">登陆</a>
第一个框中用于双重验证号码,在点击发送信息时将第二个框中输入的号码赋值
给它,防止发送信息后改动号码
js中代码:
/** * 发送手机验证码 */ function sendPhoneCode() { var mobileVal=$("#u-name-reg").val();//输入的号码 var pageFrom = "phoneLogin";//页面来源 $("#u-name-reg-first").val(mobileVal);//给第一次号码赋值 $.ajax({ url:baselocation+'/login/ajax/sendPhoneMsg', type:'post', dataType:'json', data:{ "mobileVal":mobileVal, "pageFrom":pageFrom }, success:function(result){ if(result.success==true){ layer.msg(result.message, {icon: 1, shift: 6}); var timeTicket; var timeNum = 60; clearInterval(timeTicket); /*当点击获取验证码后设置60秒计时不可点击*/ timeTicket = setInterval(function () { if (timeNum>1){ timeNum--; /*设置按钮不可点击*/ $(".mobile-yz-btn").addClass("mobile-yz-btn-no"); $(".mobile-yz-btn").attr("onclick",""); $(".mobile-yz-btn").text(timeNum+"秒后重新获取"); }else if (timeNum==1){ $(".mobile-yz-btn").text("点击获取验证码"); $(".mobile-yz-btn").attr("onclick","sendPhoneRegister()"); $(".mobile-yz-btn").removeClass("mobile-yz-btn-no"); timeNum = 60; clearInterval(timeTicket); //刷新验证码 $(".js-verify-refresh.c-green").click(); } },1000); }else{ layer.msg(result.message, {icon: 5, shift: 6}); } } }) }
消息成功发送后,提交按钮的文本框显示倒计时时间,每隔一秒触发一次事件,60秒后计时结束
在conreoller中:
//发送手机验证码 @RequestMapping("/login/ajax/sendPhoneMsg") @ResponseBody public Map<String,Object> sendPhoneMsg(HttpServletRequest request) throws ClientException { Map<String,Object> json; //获取手机号 String mobile=request.getParameter("mobileVal"); if(StringUtils.isEmpty(mobile)){ json = this.setJson(false,"号码不能为空", null); return json; } if(!WebUtils.checkMobile(mobile)){ json = this.setJson(false, "号码格式错误", null); return json; } //获取页面来源 String pageFrom=request.getParameter("pageFrom"); if(pageFrom!=null){ if(pageFrom.equals("register")){ String userName = request.getParameter("nameVal"); if(userService.checkUsername(userName)){ json = this.setJson(false,"该用户名已注册", null); return json; } if(userService.checkMobile(mobile)){ json = this.setJson(false,"该号码已注册", null); return json; } } if(pageFrom.equals("phoneLogin")){ if(!userService.checkMobile(mobile)){ json = this.setJson(false,"该号码未注册", null); return json; } } } json=userService.sendMobileCode(mobile,"_mobileCodeNum"); return json; }
进行号码判空和格式处理,同时根据pageFrom参数获取页面来源,根据“登录”或“注册”页面进行号码判断。若不符合要求则无法发送信息;若通过则调用sendMobileCode方法进行信息发送
@Override public Map<String, Object> sendMobileCode( String mobile, String cachePostfix) throws ClientException { Map<String, Object> json = new HashMap<String, Object>(); String mobileCodeNum = ""; //获得验证码 mobileCodeNum = WebUtils.getRandomNum(4);//随机验证码4为数 //先删除之前的验证码缓存 String usedMobileCodeNum = (String) cache.get(mobile+"_mobileCodeNum"); cache.remove(usedMobileCodeNum); //将验证码存入缓存 cache.set(mobile + cachePostfix, mobileCodeNum, 300); SendSmsResponse sendSmsResponse = sendSms(mobile, mobileCodeNum); if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) { //请求成功 json.put("success", Boolean.valueOf(true)); json.put("message", "短信发送成功"); json.put("entity", null); return json; } json.put("success", Boolean.valueOf(false)); json.put("message", "短信发送失败,请重试"); json.put("entity", null); return json; }
生成随机验证码:
/**获取k位由0-9的随机数字拼成的符串*/ public static String getRandomNum(int k){ String RandomNum = ""; for (int i=0;i<k;i++){ Random rd = new Random(); RandomNum += (int)Math.floor(rd.nextInt(9)); } return RandomNum; }
返回的json到ajax中,用
layer.msg(result.message, {icon: 1, shift: 6});
layer.msg(result.message, {icon: 5, shift: 6});
表示发送成功或失败
输入验证码后完成登录
点击登录条件
操作 | 号码 | 验证码 |
---|---|---|
登录 | 非空、格式、与第一次输入相同 | 非空、正确 |
js中代码:
/** * 根据手机号和验证码登陆 */ function sendPhoneCodelogin() { var mobileVal=$("#u-name-reg").val();//手机号 var mobileCode=$("#pp-randomcode-reg").val();//验证码 var firstMobile = $("#u-name-reg-first").val();//第一次输入的号码 $.ajax({ url:baselocation+'/user/ajax/phonelogin', type:'post', dataType:'json', data:{ "mobileVal":mobileVal, "mobilecode":mobileCode, "firstMobile":firstMobile }, success:function(result){ if(result.success==true){ window.location.href="${ctx}"; }else{ layer.msg(result.message, {icon: 5, shift: 6}); } } }) }
controller中代码:
/** * 手机号登录 */ @RequestMapping("/phonelogin") @ResponseBody public Map<String,Object> phoneLogin(HttpServletRequest request, HttpServletResponse response){ Map<String,Object> json = new HashMap<String,Object>(); Map<String,Object> map = new HashMap<String, Object>(); try{ //获取手机号 String mobile=request.getParameter("mobileVal"); //第一次输入的号码 String firstMobile = request.getParameter("firstMobile"); //验证码 String mobileCode=request.getParameter("mobilecode"); //从缓存提取手机验证码 String mobileCodeNum = (String) cache.get(mobile+"_mobileCodeNum"); if(StringUtils.isEmpty(mobile)){ json = this.setJson(false,"号码为空","mobile"); return json; } if(!WebUtils.checkMobile(mobile)){ json = this.setJson(false, "号码格式错误", null); return json; } if(StringUtils.isEmpty(firstMobile) || !mobile.equals(firstMobile)){ json = this.setJson(false, "系统错误", null); return json; } if(StringUtils.isEmpty(mobileCode)){ json = this.setJson(false, "验证码为空", null); return json; } if (mobileCode.equals(mobileCodeNum)){ userService.phonelogin(mobile); cache.remove(mobile+"_mobileCodeNum"); }else{ json = this.setJson(false,"验证码错误","mobile"); return json; } //进行登录操作 map.put("ipForget","true"); map.put("mobile",mobile); map.put("request",request); map.put("response",response); map=userService.queryDoUserLoginByMobile(map); json = this.setJson((boolean)map.get("success"), (String)map.get("message"), map); WebUtils.setCookie(response, UserCacheConstans.WEB_USER_LOGIN_PREFIX, (String) map.get("uuid"), 1); }catch (Exception e) { this.setAjaxException(json); logger.error("getVipInfo()---error",e); } return json; }
1.若条件不符合返回相应的信息回到ajax并用
layer.msg(result.message, {icon: 5, shift: 6});
弹框显示错误信息
2.若条件符合且验证码正确,将该用户数据封装在map对象中,调用queryDoUserLoginByMobile方法,执行登录操作
/** * 手机号登录操作 */ public Map<String,Object> queryDoUserLoginByMobile(Map<String,Object> parameterMap) throws Exception { Map map = new HashMap(); //--在线人数统计/限制 开始-- if(!OnlineUtil.ckeckLimit(map)) { return map; } //--在线人数统计/限制 结束-- HttpServletRequest request = (HttpServletRequest)parameterMap.get("request"); HttpServletResponse response = (HttpServletResponse)parameterMap.get("response"); String ipForget = (String)parameterMap.get("ipForget"); String mobile = (String)parameterMap.get("mobile"); User user = userMapper.queryUserByEmailOrMobile(mobile);//通过号码查询用户 String account = user.getUserName(); String prefix = WebUtils.getCookie(request, UserCacheConstans.WEB_USER_LOGIN_PREFIX); if(StringUtils.isNotEmpty(prefix)){ cache.remove(prefix); } if(user.getIsavalible()==2){ map.put("success",false); map.put("message","该帐号已被禁用"); return map; } cache.remove(UserCacheConstans.NAME_OR_PASS_ERR_COUNT+account); return queryDoLogin(user,ipForget,response,request); }
User user = userMapper.queryUserByEmailOrMobile(mobile);
由于号码是唯一的,所有根据号码查询获取该用户
user.getIsavalible()
若该账号被禁用,登录失败
return queryDoLogin(user,ipForget,response,request);
若该账号不被禁用,删除之前该用户的缓存,执行登录操作
/** * 登陆操作 */ public Map queryDoLogin(User user, String ipForget, HttpServletResponse response, HttpServletRequest request)throws Exception{ Map map = new HashMap(); //用户密码不能让别人看到 user.setPassword(""); String uuid = RandomUtils.simpleUUID(); //当前时间戳 Long currentTimestamp=System.currentTimeMillis(); user.setLoginTimeStamp(currentTimestamp); //当前时间 user.setLoginDatatime(new Date()); //客户端登录时间 String userLoginDatatime = URLEncoder.encode(DateUtils.format(user.getLoginDatatime(),"yyyy-MM-dd HH:mm:ss"),"UTF-8").replaceAll("\\+", "%20"); if("true".equals(ipForget)){ //缓存用户 cache.set(uuid, user,UserCacheConstans.userTime); //缓存用户cookie key(后台获取后,可以清除登录用户的缓存) cache.set(UserCacheConstans.WEB_USER_LOGIN_PREFIX+user.getUserId(), uuid,UserCacheConstans.userTime); WebUtils.setCookie(response, UserCacheConstans.WEB_USER_LOGIN_PREFIX, uuid, (UserCacheConstans.userTime/60/60/24)); WebUtils.setCookie(response, UserCacheConstans.WEB_USER_LOGINDATATIME, userLoginDatatime , (UserCacheConstans.userTime/60/60/24)); }else{ //缓存用户 cache.set(uuid, user,86400); //缓存用户cookie key(后台获取后,可以清除登录用户的缓存) cache.set(UserCacheConstans.WEB_USER_LOGIN_PREFIX+user.getUserId(), uuid,UserCacheConstans.userTime); WebUtils.setCookie(response, UserCacheConstans.WEB_USER_LOGIN_PREFIX, uuid, 1); WebUtils.setCookie(response, UserCacheConstans.WEB_USER_LOGINDATATIME, userLoginDatatime , 1); } loginCommonOperate(request,user); // 登录时把cookie中的购物车信息加到数据库中 shopcartService.addTempShopCart(request, response, Long.valueOf(user.getUserId())); map.put("success",true); map.put("message","登陆成功"); map.put("user",user); map.put("uuid",uuid); //--在线人数统计/限制 开始-- OnlineUtil.resetOnline(request, response, user.getUserId()); //--在线人数统计/限制 结束-- return map; }
将各种信息写入到缓存中,返回“登录成功”的信息
if(result.success==true){ window.location.href="${ctx}"; }
登录成功后,跳转到网站首页
基于注册发送
操作 | 账号 | 密码 | 确认密码 | 手机号 |
---|---|---|---|---|
注册 | 非空、格式 、未注册 | 非空、格式 | 非空、格式、与第一次输入相同 | 非空、格式、未注册 |
jsp中:
<input id="u-name-reg" type="text" name="key" placeholder="请输入账号(英文、数字、减号或下划线且6-24个字符)" value='' class="name-input" autocomplete="off"/> <input id="u-password-reg" type="password" name="key" placeholder="请输入密码(包含字母、数字且不小于8位)" value='' class="bui-input" autocomplete="off"/> <input id="u-password-reg-again" type="password" name="key" placeholder="请确认密码" value='' style="margin:20px 0px" class="bui-input" autocomplete="off"/> <input id="u-phone-reg" type="text" name="key" placeholder="请输入手机号码" value='' class="name-input" autocomplete="off"/> <input id="pp-randomcode-reg" class="name-input" placeholder="请输入验证码" name="" value="" onkeyup="$(this).next().next().next().html('');" maxlength="4" type="text"> <a class="vam ml10 disIb fl mobile-yz-btn" href="javascript:void(0)" onclick="sendPhoneCode()" title="">点击获取验证码</a> <a class="loginBtn" type="button" onclick="Register()" title="注 册">注册</a>
1.可以同上面所说的“登录”一样将获取到的值通过ajax发送到controller中处理,再将结果返回
2.可以在js的function()中获取各个框中输入的值作判断处理,若不符合要求则无法跳到controller中处理,本例采用这种方式
//发送验证码 function sendPhoneCode() { var pageFrom = "register"; var mobileVal=$("#u-phone-reg").val(); var nameVal = $("#u-name-reg").val(); if (nameVal == null || nameVal == "") { layer.msg("请输入账号", {icon: 5, shift: 6}); return; } if (!isNaN(nameVal)) { layer.msg("账号不能全为数字", {icon: 5, shift: 6}); return; } if (nameVal.length < 6 || nameVal.length > 24) { layer.msg("账号长度为6-24个字符", {icon: 5, shift: 6}); return; } if (usernameRegex.test(nameVal) == false) {//账号格式 layer.msg("账号仅支持英文、数字、减号或下划线", {icon: 5, shift: 6}); return; } var password = $("#u-password-reg").val(); if (password == null || password == "") { layer.msg("请输入密码", {icon: 5, shift: 6}); return; } password = encrypt(password); var passwordAgain = $("#u-password-reg-again").val(); if (passwordAgain == null || passwordAgain == "") { layer.msg("请确认密码", {icon: 5, shift: 6}); return; } passwordAgain = encrypt(passwordAgain); if (password!=passwordAgain) { layer.msg("两次密码不一致", {icon: 5, shift: 6}); return; } $.ajax({ url:baselocation+'/login/ajax/sendPhoneMsg', type:'post', dataType:'json', data:{ "nameVal":nameVal, "mobileVal":mobileVal, "pageFrom":pageFrom }, success:function(result){ if(result.success==true){ layer.msg("短信发送成功", {icon: 1, shift: 6}); var timeTicket; var timeNum = 60; //$("#phoneClick").css("visibility","hidden"); // $("#recoverPhoneClick").css("visibility","visible"); clearInterval(timeTicket); /*当点击获取验证码后设置60秒计时不可点击*/ timeTicket = setInterval(function () { if (timeNum>1){ timeNum--; /*设置按钮不可点击*/ $(".mobile-yz-btn").addClass("mobile-yz-btn-no"); $(".mobile-yz-btn").attr("onclick",""); $(".mobile-yz-btn").text(timeNum+"秒后重新获取"); }else if (timeNum==1){ $(".mobile-yz-btn").text("点击获取验证码"); $(".mobile-yz-btn").attr("onclick","sendPhoneRegister()"); $(".mobile-yz-btn").removeClass("mobile-yz-btn-no"); timeNum = 60; clearInterval(timeTicket); //刷新验证码 $(".js-verify-refresh.c-green").click(); } },1000); }else{ layer.msg(result.message, {icon: 5, shift: 6}); } } }) }
其余代码跟登录相似,只是pageFrom的值不同,这样controller中才会根据不同页面对“用户名”和“手机号”作判断。若该账号或手机号已注册,则无法发送验证码,相比在点击“注册”时对之作判断,可以减少很多“无用”信息
if(pageFrom.equals("register")){ String userName = request.getParameter("nameVal"); if(userService.checkUsername(userName)){ json = this.setJson(false,"该用户名已注册", null); return json; } if(userService.checkMobile(mobile)){ json = this.setJson(false,"该号码已注册", null); return json; } }
输入验证码后完成注册
点击注册条件
操作 | 号码 | 验证码 |
---|---|---|
注册 | 非空、格式、未注册、与发送验证码的号码相同 | 非空、正确 |
其余逻辑均与“登录”时相似,注册成功后,登录该用户,显示主页面
Tips:本人第一篇博客,若有不足之处,欢迎大家予以斧正。
- 注册/找回密码等功能中发送手机验证码后倒计时效果的实现(基于vue)
- Angular获取手机验证码实现移动端登录注册功能
- Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
- Ajax-HelloWorld(运用AJAX技术实现会员注册登录验证功能)
- jQuery+ajax+php实现注册登录功能
- jquery+jsp+servlet+ajax实现注册功能,ajax校验用户名、验证码等
- vue 实现通过手机发送短信验证码注册功能
- 基于forms组件和Ajax实现注册功能
- spring boot中如何实现在手机注册和登录时获取验证码(阿里短信服务)
- Android Studio-手把手教你基于SQLLITE实现登录注册功能
- 基于struts2和hibernate实现登录和注册功能
- PHP实现注册登录功能完整教程及代码 含验证码
- 基于Spring Security实现手机验证码登录
- 基于PHP实现用户注册登录功能
- Android手机注册登录时获取验证码之后倒计时功能(知识点总结)
- struts2+hibernate4.1+spring4.1+ajax+HTML+css暂时实现登录注册功能
- php实现Ajax带有验证码的登陆注册功能
- jquery+jsp+servlet+ajax实现注册功能,ajax校验用户名、验证码等(转自他人)
- 基于Ajax和forms组件实现注册功能的实例代码
- 基于Ajax技术实现无刷新用户登录功能