비밀번호 변경 페이지 추가

This commit is contained in:
현성필
2023-08-07 10:45:13 +09:00
parent 42efd57b62
commit 2e11742b26
14 changed files with 2094 additions and 24 deletions
@@ -1,5 +1,6 @@
package com.eactive.httpmockserver.common.exception;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -10,6 +11,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
import java.time.LocalDateTime;
@Order(1)
@RestControllerAdvice(annotations = RestController.class)
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@@ -3,6 +3,7 @@ package com.eactive.httpmockserver.common.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -11,6 +12,7 @@ import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice(annotations = Controller.class)
@Order(2)
public class PortalGlobalExceptionHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -1,6 +1,7 @@
package com.eactive.httpmockserver.config;
import com.eactive.httpmockserver.common.entity.EnabledStatus;
import com.eactive.httpmockserver.common.exception.UserNotFoundException;
import com.eactive.httpmockserver.login.controller.LoginController;
import com.eactive.httpmockserver.user.entity.StaffUser;
import com.eactive.httpmockserver.user.entity.User;
@@ -29,23 +30,25 @@ public class PortalAuthenticationFailureHandler implements AuthenticationFailure
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = {AuthenticationException.class, UserNotFoundException.class})
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
String username = request.getParameter("id");
try {
User user = userService.findByUserId(username);
if (user != null) {
user.setLockCnt(user.getLockCnt() + 1);
if (user.getLockCnt() >= 5) {
user.setLockAt(EnabledStatus.Y);
}
User user = userService.findByUserId(username);
user.setLockCnt(user.getLockCnt() + 1);
if (user.getLockCnt() >= 5) {
user.setLockAt(EnabledStatus.Y);
staffUserRepository.save((StaffUser) user);
}
} catch (UserNotFoundException ignored) {
}
staffUserRepository.save((StaffUser) user);
request.getSession().setAttribute(LoginController.LOGIN_MESSAGE, exception.getMessage());
request.getSession().setAttribute(LoginController.LOGIN_MESSAGE, exception.getLocalizedMessage());
String contextPath = request.getContextPath();
response.sendRedirect(contextPath + "/login");
}
}
@@ -30,9 +30,9 @@ public class PortalAuthenticationManager implements AuthenticationManager {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
String username = token.getName();
String password = token.getCredentials().toString();
String encryptPassword = encryptionUtil.encryptPassword(password, username);
UserDetails user = userService.loadUserByUsername(username);
String encryptPassword = encryptionUtil.encryptPassword(password, username);
if (!user.isEnabled()) {
throw new DisabledException("계정이 " + ((User) user).getStatus().getDescription() + "상태입니다. 관리자에게 문의하세요.");
@@ -47,8 +47,6 @@ public class PortalAuthenticationManager implements AuthenticationManager {
UsernamePasswordAuthenticationToken authorityToken = new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());
authorityToken.setDetails(user);
SecurityContextHolder.getContext().setAuthentication(authorityToken);
((User) user).setLockCnt(0);
userService.updateUser((User) user);
return authorityToken;
}
@@ -3,10 +3,13 @@ package com.eactive.httpmockserver.config;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
/**
* @author
@@ -26,7 +26,7 @@ public class AccountController {
@GetMapping("/change_password.do")
public String changePassword(ModelMap model, @ModelAttribute("passwordChangeRequest") PasswordChangeRequestDTO passwordChangeRequestDTO) {
return "apps/main/updatePw";
return "page/updatePw";
}
@PostMapping(value = "/update_password.do")
@@ -39,7 +39,7 @@ public class AccountController {
if (result.hasErrors()) {
model.addAttribute("errors", result);
return "apps/main/updatePw";
return "page/updatePw";
}
String oldPassword = passwordChangeRequestDTO.getOldPassword();
@@ -51,7 +51,7 @@ public class AccountController {
model.addAttribute("resultMsg", resultMsg);
model.addAttribute("passwordChangeRequest", new PasswordChangeRequestDTO());
return "apps/main/updatePw";
return "page/updatePw";
}
@@ -28,7 +28,11 @@ public class UserService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return staffUserRepository.findByUserId(username).orElseThrow(() -> new UserNotFoundException(USER_NOT_FOUND_MESSAGE));
try {
return findByUserId(username);
} catch (UserNotFoundException e) {
throw new UsernameNotFoundException(e.getMessage());
}
}
public User findByUserId(String userId) {
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.navercorp.com/lucy-xss-servlet">
<defenders>
<!-- XssPreventer 등록 -->
<defender>
<name>xssPreventerDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssPreventerDefender</class>
</defender>
<!-- XssSaxFilter 등록 -->
<defender>
<name>xssSaxFilterDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssSaxFilterDefender</class>
<init-param>
<param-value>lucy-xss-sax.xml</param-value> <!-- lucy-xss-filter의 sax용 설정파일 -->
<param-value>false</param-value> <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
</init-param>
</defender>
<!-- XssFilter 등록 -->
<defender>
<name>xssFilterDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssFilterDefender</class>
<init-param>
<param-value>lucy-xss.xml</param-value> <!-- lucy-xss-filter의 dom용 설정파일 -->
<param-value>true</param-value> <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
</init-param>
</defender>
</defenders>
<!-- default defender 선언, 필터링 시 지정한 defender가 없으면 여기 정의된 default defender를 사용해 필터링 한다. -->
<default>
<defender>xssFilterDefender</defender>
</default>
<!-- global 필터링 룰 선언 -->
<global>
<!-- 모든 url에서 들어오는 globalParameter 파라메터는 필터링 되지 않으며
또한 globalPrefixParameter1로 시작하는 파라메터도 필터링 되지 않는다.
globalPrefixParameter2는 필터링 되며 globalPrefixParameter3은 필터링 되지 않지만
더 정확한 표현이 가능하므로 globalPrefixParameter2, globalPrefixParameter3과 같은 불분명한 표현은 사용하지 않는 것이 좋다. -->
<params>
<param name="globalParameter" useDefender="false" />
<param name="globalPrefixParameter1" usePrefix="true" useDefender="false" />
<param name="globalPrefixParameter2" usePrefix="true" />
<param name="globalPrefixParameter3" usePrefix="false" useDefender="false" />
</params>
</global>
<!-- url 별 필터링 룰 선언 -->
<url-rule-set>
</url-rule-set>
</config>
File diff suppressed because it is too large Load Diff
@@ -41,4 +41,12 @@ lastLockDate=Lock Date
lastPasswordChangeDate=Last Password Change Date
common.nodata.msg=No Data
name=Name
common.delete.msg=Confirm to Delete?
common.delete.msg=Confirm to Delete?
comUssUmt.userManagePasswordUpdt.oldPass=Current Password
comUssUmt.userManagePasswordUpdt.pass=Password
comUssUmt.userManagePasswordUpdt.passConfirm=Password Confirmation
button.cancel=cancel
success.common.update=Successfully chnaged.
fail.user.passwordUpdate2=New passwords not matched.
fail.user.passwordUpdate1=Current password is incorrect.
@@ -47,4 +47,12 @@ lastLockDate=\uC7A0\uAE40 \uC77C\uC2DC
lastPasswordChangeDate=\uBE44\uBC00\uBC88\uD638 \uBCC0\uACBD \uC77C\uC2DC
common.nodata.msg=\uB370\uC774\uD130\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
name=\uC774\uB984
common.delete.msg=\uC0AD\uC81C \uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?
common.delete.msg=\uC0AD\uC81C \uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?
comUssUmt.userManagePasswordUpdt.pass=\uBE44\uBC00\uBC88\uD638
comUssUmt.userManagePasswordUpdt.passConfirm=\uBE44\uBC00\uBC88\uD638\uD655\uC778
comUssUmt.userManagePasswordUpdt.oldPass=\uAE30\uC874 \uD328\uC2A4\uC6CC\uB4DC
button.cancel=\uCDE8\uC18C
success.common.update=\uC815\uC0C1\uC801\uC73C\uB85C \uBCC0\uACBD\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
fail.user.passwordUpdate2=\uBE44\uBC00\uBC88\uD638\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
fail.user.passwordUpdate1=\uAE30\uC874 \uBE44\uBC00\uBC88\uD638\uAC00 \uD2C0\uB838\uC2B5\uB2C8\uB2E4.
@@ -35,7 +35,7 @@
<a href="/login" class="nav-link">로그인</a>
</li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a href="/mypage.do" class="nav-link">비밀번호 변경</a></li>
<a href="/change_password.do" class="nav-link">비밀번호 변경</a></li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a href="/actionLogout.do" class="nav-link">로그 아웃</a></li>
</ul>
@@ -558,8 +558,6 @@
select.empty();
sidemenu.empty();
let filter = $('#filter_text').val();
for (let i = 0; i < collections.length; i++) {
let template = $('#collectionTemplate').children().clone();
@@ -809,8 +807,6 @@
});
},
saveAPIRequest: function(model){
console.log(model);
this.currentAjaxRequest = $.ajax({
url: '/mgmt/collections/{collectionId}/apis/save.do'.replace('{collectionId}', model.collectionId),
type: 'POST',
@@ -0,0 +1,83 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{/layout/default_layout}">
<body>
<section layout:fragment="contentFragment">
<div class="container m-0">
<div class="card mt-2">
<div class="card-header">
<h1>비밀 번호 변경 </h1>
</div>
<div class="card-body">
<form name="passwordChangeRequest" id="passwordChangeRequest" class="form-horizontal form-horizontal_l" method="post" th:action="@{/update_password.do}"
th:object="${passwordChangeRequest}">
<!-- 기존 비밀번호 -->
<div class="form-floating">
<input class="form-control mb-3" th:classappend="${#fields.hasErrors('oldPassword')}? 'is-invalid'" name="oldPassword" id="oldPassword" th:field="*{oldPassword}" type="password"
size="20" value="" maxlength="100" required>
<label for="oldPassword" class="must" th:text="#{comUssUmt.userManagePasswordUpdt.oldPass}"></label>
<th:block th:each="err : ${#fields.errors('oldPassword')}">
<div th:text="${err}" class="invalid-feedback"></div>
</th:block>
</div>
<div class="form-floating">
<input class="form-control mb-3" th:classappend="${#fields.hasErrors('newPassword')}? 'is-invalid'" name="newPassword" id="newPassword" th:field="*{newPassword}" type="password"
size="20" value="" maxlength="100" required>
<label for="newPassword" class="must" th:text="#{comUssUmt.userManagePasswordUpdt.pass}"></label>
<th:block th:each="err : ${#fields.errors('newPassword')}">
<div th:text="${err}" class="invalid-feedback"></div>
</th:block>
</div>
<!-- 비밀번호확인 -->
<div class="form-floating">
<input class="form-control mb-3" th:classappend="${#fields.hasErrors('newPassword2')}? 'is-invalid'" name="newPassword2" id="newPassword2" th:field="*{newPassword2}"
type="password" size="20" value="" maxlength="100" required>
<label for="newPassword2" class="must" th:text="#{comUssUmt.userManagePasswordUpdt.passConfirm}"></label>
<th:block th:each="err : ${#fields.errors('newPassword2')}">
<div th:text="${err}" class="invalid-feedback"></div>
</th:block>
</div>
</form>
</div>
<div class="card-footer">
<button type="button" class="btn btn-primary btn_update"><i class="fa-sharp fa-solid fa-floppy-disk"></i> 저장</button>
<a th:href="@{/mypage.do}" class="btn btn-primary" th:title="#{button.cancel}"><i class="fa-sharp fa-solid fa-cancel"></i> [[#{button.cancel}]]</a>
</div>
</div>
</div>
</section>
</body>
<th:block layout:fragment="contentScript">
<script>
$(function () {
document.getElementById("passwordChangeRequest").oldPassword.focus();
let btnUpdate = document.querySelector(".btn_update");
btnUpdate.addEventListener("click", function (event) {
let form = document.getElementById("passwordChangeRequest");
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
} else {
form.submit();
}
form.classList.add('was-validated');
});
})
</script>
<script th:if="${resultMsg != null}">
$(function () {
var resultMsg = '[[#{${resultMsg}}]]';
if (resultMsg !== "") {
alert(resultMsg);
}
})
</script>
</th:block>
</html>