为用户注册界面添加修改密码选项
前情回顾
之前跟着 github 上一个简易商城项目练手的时候,发现原po老师在用户注册界面只设置了登录、注册选项,没有修改密码的按钮,这对于我们的常识来说这个界面是做的还不够的,在跟着实现完一遍商城项目后,自己添加了密码修改这一选项。记录具体思路和实现。
最开始的登录界面:
想要实现成这样的:
然后点击 忘记密码? 跳转到修改密码界面:
具体实现
由于这个操作是针对用户的,所以直接在 UserSevice 接口里面添加一个 changePassword 方法:
1 void changePassword(String telephone, String password) throws BusinessException;
在其实现类里面,实现 changPassword 方法:
1. 根据电话获取用户,判断该电话号码是否注册过,如果没有注册过,则抛出异常提示用户,该电话尚未注册。如果注册过,则执行后面代码。
2. 用户的基本信息(id、姓名、电话、性别)和密码信息(密码、用户id)存放在数据库里不同的表里面,分别为 user_info 和 user_password。在利用Mybatis为对应表生成映射文件.xml、dao、dataobject的时候,就分别有两种,基本信息映射和密码信息映射,根据电话信息修改密码,首先要根据电话获取用户id,然后在密码信息映射文件中添加 sql 方法:
1 <update id="updateByUserIdSelective" parameterType="com.miaoshaproject.dataobject.UserPasswordDO"> 2 update user_password 3 <set> 4 <if test="encrptPassword != null"> 5 encrpt_password = #{encrptPassword,jdbcType=VARCHAR}, 6 </if> 7 <if test="userId != null"> 8 user_id = #{userId,jdbcType=INTEGER}, 9 </if> 10 </set> 11 where user_id = #{userId,jdbcType=INTEGER} 12 </update>
在其对应 dao 接口添加方法:
1 int updateByUserIdSelective(UserPasswordDO record);
这样我们就可以在 UserServiceImpl 里根据用户电话,更新用户密码了。
UserServiceImpl
1 @Override 2 @Transactional 3 public void changPassword(String telephone, String password) throws BusinessException { 4 // 根据电话获取用户,判断该电话号码是否注册过,如果没有注册过,则抛出异常 5 UserDO userDO = userDOMapper.selectByTelephone(telephone); 6 if (userDO == null) { 7 throw new BusinessException(EnumBusinessError.USER_NOT_EXIST, "用户还未注册,请注册"); 8 } 9 10 try { 11 // 根据 telephone 获取 用户id。 12 UserPasswordDO userPasswordDO = new UserPasswordDO(); 13 userPasswordDO.setEncrptPassword(password); 14 userPasswordDO.setUserId(userDOMapper.selectByTelephone(telephone).getId()); 15 // 需要在 UserPasswordDOMapper 里面添加根据用户 id 更新密码的方法吗? 16 userPasswordDOMapper.updateByUserIdSelective(userPasswordDO); 17 } catch (Exception ex) { 18 System.out.println(ex); 19 } 20 }
控制层
1 // 用户修改密码接口 2 @RequestMapping(value = "/changePassword", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED}) 3 @ResponseBody 4 public CommonReturnType changePassword(@RequestParam(name = "telephone") String telephone, 5 @RequestParam(name = "otpCode") String otpCode, 6 @RequestParam(name = "password") String password 7 ) throws BusinessException { 8 9 // 验证手机号和获取到的 otpCode 相匹配 10 System.out.println("new otpCode:" + this.httpServletRequest.getSession().getAttribute(telephone)); 11 String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(telephone); 12 if (!StringUtils.equals(otpCode, inSessionOtpCode)) { 13 throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码不匹配"); 14 } 15 16 // 如果匹配,则调用 service 服务进行修改密码 17 userService.changPassword(telephone, this.EncodeByBase64(password)); 18 19 return CommonReturnType.create(null); 20 }
前端的展示页面
由于在进行修改密码的时候,用户输入手机号,获取一个验证信息 otpCode,这个过程和用户最开始注册的时候是一致的,新用户注册的时候输入手机号后台也会传一个 otpCode 给用户,用来验证身份。所以获取 otpCode 这个接口代码可以复用,但是问题来了,新用户在注册的时候,在获取otpCode页面,如果获取成功,则直接跳转用户注册界面,需要填写所有的基本信息和密码信息。成功后跳转到登录界面。但是对于修改密码这一操作来说,获取 otpCode 之后,应该跳转到修改密码页面,只需要填写用户电话、otpCode、新密码。然后再跳转到登录界面。该如何区分某个时刻的获取 otpCode 界面是跳到新用户注册界面呢,还是修改密码界面呢?
解决办法是用户在登录界面点击 忘记密码? 之后, 直接跳转到 修改密码界面,该界面包含 获取otpCode和提交修改两个选项,分别对应后端的获取 otpCode 接口和修改密码接口,这样后端的代码就不会复用了。
登录页面代码
1 <html> 2 <head> 3 <meta charset="UTF-8"> 4 <link href="static/assets/global/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> 5 <link href="static/assets/global/css/components.css" rel="stylesheet" type="text/css"/> 6 <link href="static/assets/admin/pages/css/login.css" rel="stylesheet" type="text/css"/> 7 <script src="static/assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script> 8 <title>Title</title> 9 </head> 10 <body class="login"> 11 <div class="content"> 12 <h3 class="form-title">用户登录</h3> 13 <div class="form-group"> 14 <label class="control-label">手机号</label> 15 <div> 16 <input class="form-control" type="text" placeholder="手机号" name="telephone" id="telephone"/> 17 </div> 18 </div> 19 <div class="form-group"> 20 <label class="control-label">密码</label> 21 <div> 22 <input class="form-control" type="password" placeholder="密码" name="password" id="password"/> 23 </div> 24 </div> 25 <div class="form-actions"> 26 <button class="btn blue" id="login" type="submit"> 27 登录 28 </button> 29 <button class="btn green" id="register" type="submit"> 30 注册 31 </button> 32 <button class="btn red" id="changePassword" type="submit"> 33 忘记密码? 34 </button> 35 </div> 36 </div> 37 38 </body> 39 40 <script> 41 jQuery(document).ready(function () { 42 43 //绑定注册按钮的click事件用于跳转到注册页面 44 $("#register").on("click",function () { 45 window.location.href = "getOtp.html"; 46 }); 47 48 //绑定登录按钮的click事件用于登录 49 $("#login").on("click",function () { 50 51 var telephone=$("#telephone").val(); 52 var password=$("#password").val(); 53 if (telephone == null || telephone == "") { 54 alert("手机号不能为空"); 55 return false; 56 } 57 if (password==null || password=="") { 58 alert("密码不能为空"); 59 return false; 60 } 61 62 //映射到后端@RequestMapping(value = "/login", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED}) 63 $.ajax({ 64 type:"POST", 65 contentType:"application/x-www-form-urlencoded", 66 url:"http://localhost:8090/user/login", 67 data:{ 68 "telephone":telephone, 69 "password":password 70 }, 71 xhrFields:{withCredentials:true}, 72 73 success:function (data) { 74 if (data.status == "success") { 75 alert("登录成功"); 76 window.location.href = "listitem.html"; 77 }else { 78 alert("登录失败,原因为" + data.data.errMsg); 79 } 80 }, 81 error:function (data) { 82 alert("登录失败,原因为"+data.responseText); 83 } 84 }); 85 return false; 86 }); 87 88 //绑定 修改密码按钮 的click事件用于跳转到获取 changepassword 页面 89 $("#changePassword").on("click",function () { 90 window.location.href = "changepassword.html"; 91 }); 92 93 }); 94 </script> 95 </html>
修改密码界面
1 <html> 2 <head> 3 <meta charset="UTF-8"> 4 <link href="static/assets/global/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> 5 <link href="static/assets/global/css/components.css" rel="stylesheet" type="text/css"/> 6 <link href="static/assets/admin/pages/css/login.css" rel="stylesheet" type="text/css"/> 7 <script src="static/assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script> 8 <title>Title</title> 9 </head> 10 11 <body class="login"> 12 <div class="content"> 13 <h3 class="form-title">修改密码</h3> 14 <div class="form-group"> 15 <label class="control-label">手机号</label> 16 <div> 17 <input class="form-control" type="text" placeholder="手机号" name="telephone" id="telephone"/> 18 </div> 19 </div> 20 <div class="form-group"> 21 <label class="control-label">点击获取验证码</label> 22 <div> 23 <input class="form-control" type="text" placeholder="验证码" name="otpCode" id="otpCode"/> 24 </div> 25 </div> 26 27 <div class="form-actions"> 28 <button class="btn blue" id="getOtp" type="submit"> 29 获取otp短信 30 </button> 31 </div> 32 33 34 <div class="form-group"> 35 <label class="control-label">新密码</label> 36 <div> 37 <input class="form-control" type="password" placeholder="密码" name="password" id="password"/> 38 </div> 39 </div> 40 41 <div class="form-actions"> 42 <button class="btn blue" id="changePassword" type="submit"> 43 提交更改 44 </button> 45 </div> 46 </div> 47 48 </body> 49 50 <script> 51 jQuery(document).ready(function () { 52 53 //绑定otp的click事件用于向后端发送获取手机验证码的请求 54 $("#getOtp").on("click",function () { 55 56 var telephone=$("#telephone").val(); 57 if (telephone==null || telephone=="") { 58 alert("手机号不能为空"); 59 return false; 60 } 61 62 //映射到后端@RequestMapping(value = "/getOtp", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED}) 63 $.ajax({ 64 type:"POST", 65 contentType:"application/x-www-form-urlencoded", 66 url:"http://localhost:8090/user/getOtp", 67 data:{ 68 "telephone":$("#telephone").val(), 69 }, 70 xhrFields:{withCredentials:true}, 71 success:function (data) { 72 if (data.status == "success") { 73 alert("otp已经发送到了您的手机,请注意查收"); 74 // window.location.href="register.html"; 75 }else { 76 alert("otp发送失败,原因为" + data.data.errMsg); 77 } 78 }, 79 error:function (data) { 80 alert("otp发送失败,原因为"+data.responseText); 81 } 82 }); 83 return false; 84 }); 85 86 //绑定 changePassword 按钮的click事件 87 $("#changePassword").on("click",function () { 88 89 var telephone=$("#telephone").val(); 90 var otpCode=$("#otpCode").val(); 91 var password=$("#password").val(); 92 93 if (telephone==null || telephone=="") { 94 alert("手机号不能为空"); 95 return false; 96 } 97 if (otpCode==null || otpCode=="") { 98 alert("验证码不能为空"); 99 return false; 100 } 101 if (password==null || password=="") { 102 alert("密码不能为空"); 103 return false; 104 } 105 106 //映射到后端@RequestMapping(value = "/changePassword", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED}) 107 $.ajax({ 108 type:"POST", 109 contentType:"application/x-www-form-urlencoded", 110 url:"http://localhost:8090/user/changePassword", 111 data:{ 112 "telephone":telephone, 113 "otpCode":otpCode, 114 "password":password, 115 }, 116 xhrFields:{withCredentials:true}, 117 success:function (data) { 118 if (data.status=="success") { 119 alert("修改成功"); 120 window.location.href = "login.html"; 121 }else { 122 alert("修改失败,原因为" + data.data.errMsg); 123 } 124 }, 125 error:function (data) { 126 alert("修改失败,原因为"+data.responseText); 127 } 128 }); 129 return false; 130 }); 131 }); 132 </script> 133 </html>
总结
emmmmm感觉还可以找到更好的解决方式,后面遇到了再来考虑下。