spring実戦:パスワードの更新
首先先加一个页面。数据库中加一行:
INSERT INTO role_group VALUES ('RG00007', 'ログインパスワード変更', '/user/changepassswd', 65535, 7, '2021-10-29 16:00:00', '2030-11-01 00:00:00', 1);
相应地,在UserCtrl中映射这个地址'/user/changepassswd'
,
@RequestMapping(value="/user/changepassswd") @Role(roles = {BaseRole.R16384, BaseRole.R32768}) public String changePassword(Model model) { return "user/changepassword"; }
建立一个模板changepassword.html
<div class="menuzonediv container"> <form id="frmUserChangePasswd"> <div class="form-group"> <label for="txtPrevPasswd">現在のパスワード</label> <input class="form-control useraddinputstyle" type="password" name="prevPassword" id="txtPrevPasswd" autocomplete="off" value="prevPass"> </div> <div class="form-group"> <label for="txtNewPasswd">新しいパスワード</label> <input class="form-control useraddinputstyle" type="password" name="newPassword" id="txtNewPasswd" autocomplete="off" value="newPass2"> </div> <div class="form-group"> <label for="txtNewPasswdRe">新しいパスワード(確認)</label> <input class="form-control useraddinputstyle" type="password" name="newPasswordRe" id="txtNewPasswdRe" autocomplete="off" value="newPass3"> </div> <div id="alertSuccess" class="alert alert-success" role="alert" style="display:none;"> パスワードを更新しました。 </div> <div id="alertWarning" class="alert alert-warning" role="alert" style="display:none;"> <span id="warningMessage"></span> </div> <input type="button" class="conditionbutton1" id="btnChangePasswd" value="更新"> </form> </div> <script type="text/javascript"> $(document).ready(function() { $("#topDispTitle").html("ログインパスワード変更"); $("#dispTitleArea").removeClass("d-none"); }); function showSuccessAlert() { $("#alertSuccess").show(); setTimeout('$("#alertSuccess").fadeOut();',1200); } function showWarningAlert(message) { $("#warningMessage").html(message); $("#alertWarning").show(); setTimeout('$("#alertWarning").fadeOut();',1200); } </script>
index.js中加入此更新按钮的动作
$(document).on('click', '#btnChangePasswd', function() { var transJson = parseFormData($("#frmUserChangePasswd")); console.log(transJson); $.ajax({ url: TRIAL_CONTEXT_PATH + '/user/changepswordAction', data: transJson, type: 'post', contentType: "application/json" }).done(function(data) { console.log(data); //通信成功時の処理 if(data=="Success"){ //チェック成功時の処理 showSuccessAlert(); } else if(data=="E0018") { //ErrorSituation 1 // message is 「使用できる文字種は大小英文字、数字、記号の全てを組み合わせて、8文字以上、12文字以下です。」 showWarningAlert("使用できる文字種は大小英文字、数字、記号の全てを組み合わせて、8文字以上、12文字以下です。"); } else if(data=="E0019") { //ErrorSituation 2 // message is 「新パスワード」と「新しいパスワード(確認)」が一致していません。」 showWarningAlert("新パスワード」と「新しいパスワード(確認)」が一致していません。"); } else if(data=="E0020") { //ErrorSituation 2 // message is 「現在のパスワードが違います。」 showWarningAlert("現在のパスワードが違います。"); } }).fail(function(xhr) { //通信失敗時の処理 showErrorModal("更新に異常が発生しました。", $('#errorMessage'), $('#modalMsgBox')); }); });
然后实现这个post的动作。在userCtrl类中
@RequestMapping(value="/user/changepswordAction",method = RequestMethod.POST) @ResponseBody @Role(roles = {BaseRole.R16384, BaseRole.R32768}) public String changePasswordAction(@RequestBody PasswordDto passDto,Model model) { UserInfo userInfo = (UserInfo) httpSession.getAttribute(SysConstants.LOGIN_USER); if (Objects.isNull(userInfo)) { return "user/login"; } if(!usersService.checkPassword(userInfo.getUserId(),passDto.getPrevPassword())) { //NG: old password wrong return "E0020"; }else if(!passDto.getNewPassword().equals(passDto.getNewPasswordRe())) { //NG: password not equals return "E0019"; } // (↑) password valid OK; // (↓) password format check if( !StringUtils.passwordValid(passDto.getNewPassword()) ) { return "E0018"; } else { // password OK, update to Database if(!usersService.updateUserPassword(userInfo.getUserId(),passDto.getNewPassword())) { return "E0015"; } else { return "Success"; } } }
这儿第21行是自己添加的StringUtils类,在utils路径下。首先新建这个类,并且在userCtrl类中使用时需要在最上边import进来。
这个StringUtils就是处理字符串的函数,这儿主要是处理密码,检查密码长度、分别存在大小写和数字。大写判断用循环逻辑,后边使用正则表达式进行检查。(当然判断大写的逻辑也可以用正则式"[A-Z]"
)。
package jp.co.basenet.trial.utils; import java.util.regex.Pattern; import java.util.regex.Matcher; public class StringUtils { private static boolean hasUppercase(String passwd) { final String upperText = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(char c:passwd.toCharArray()){ if(upperText.indexOf(String.valueOf(c))>=0){ return true; } } return false; } private static boolean hasLowercase(String passwd) { Pattern p = Pattern.compile("[a-z]"); Matcher m = p.matcher(passwd); return m.find(); } private static boolean hasDigital(String passwd) { Pattern p = Pattern.compile("\\d"); Matcher m = p.matcher(passwd); return m.find(); } public static boolean passwordValid(String passwd) { return ( (8<=passwd.length() && passwd.length()<=12) && hasUppercase(passwd) && hasLowercase(passwd) && hasDigital(passwd) ); } }
这里处理完成,就可以将密码加到数据库里了。先在UserService里加个接口,然后在userServiceImpl中实现。用userInfoResposity更新到SQL中,用xml写SQL语句。
UserService
类:
Boolean updateUserPassword(String userId,String newPasswd);
UserServiceImpl
类:
public Boolean updateUserPassword(String userId,String newPasswd) { Optional<UserInfo> userOptional = userInfoRepository.findById(userId); if (!userOptional.isPresent()) { return false; } UserInfo userInfo = userOptional.get(); String userNewPasswordSha = SHA256Utils.getSHA256(userId + newPasswd); userInfo.setUserPassword(userNewPasswordSha); userInfoRepository.updateUserPassword(userInfo); return true; }
UserInfoMapper
类:
void updateUserPassword(UserInfo userinfo);
UserInfoMapper.xml
:
<update id="updateUserPassword" parameterType="jp.co.basenet.trial.jpa.model.UserInfo"> update user_info set user_password=#{userPassword}, update_datetime=#{updateDatetime}, update_user_id=#{updateUserId} where user_id = #{userId} </update>