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>