개인정보 페이지 비밀번호 변경 기능 추가.
parent
c51c1649ad
commit
2f8fc492f8
|
|
@ -34,7 +34,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests() // 페이지 권한 설정
|
||||
.antMatchers("/board/**").hasRole(Role.USER.name()) // USER, ADMIN 접근 허용
|
||||
.antMatchers("/info").hasRole(Role.USER.name()) // USER, ADMIN 접근 허용
|
||||
.antMatchers("/info/**").hasRole(Role.USER.name()) // USER, ADMIN 접근 허용
|
||||
.antMatchers("/admin/**").hasRole(Role.ADMIN.name()) // ADMIN만 접근 허용
|
||||
.antMatchers("/user/login").permitAll() // 로그인 페이지는 권한 없이 접근 허용
|
||||
.and() // 로그인 설정
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
package com.dbnt.kcgfilemanager.controller;
|
||||
|
||||
import com.dbnt.kcgfilemanager.model.CategoryRole;
|
||||
import com.dbnt.kcgfilemanager.model.UserInfo;
|
||||
import com.dbnt.kcgfilemanager.service.BoardCategoryService;
|
||||
import com.dbnt.kcgfilemanager.service.CategoryRoleService;
|
||||
import com.dbnt.kcgfilemanager.service.CommonCodeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.security.Principal;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
|
|
@ -22,18 +17,17 @@ public class BaseController {
|
|||
|
||||
private final CommonCodeService commonCodeService;
|
||||
private final BoardCategoryService boardCategoryService;
|
||||
private final CategoryRoleService categoryRoleService;
|
||||
|
||||
@GetMapping("/")
|
||||
public ModelAndView loginCheck(Principal principal, HttpSession session) {
|
||||
public ModelAndView loginCheck(@AuthenticationPrincipal UserInfo loginUser, HttpSession session) {
|
||||
ModelAndView mav = null;
|
||||
if(principal == null){
|
||||
if(loginUser == null){
|
||||
mav = new ModelAndView("redirect:/user/login");
|
||||
}else{
|
||||
session.setAttribute("positionList", commonCodeService.selectCommonCodeValue("POSITION"));
|
||||
session.setAttribute("departmentList", commonCodeService.selectCommonCodeValue("DEPARTMENT"));
|
||||
session.setAttribute("categoryList", boardCategoryService.selectBoardCategoryAll(null, 1));
|
||||
if(((UserInfo)((UsernamePasswordAuthenticationToken) principal).getPrincipal()).getUserRole().indexOf("ADMIN")>0){
|
||||
if(loginUser.getUserRole().indexOf("ADMIN")>0){
|
||||
mav = new ModelAndView("redirect:/admin/main");
|
||||
}else{
|
||||
mav = new ModelAndView("redirect:/board/main");
|
||||
|
|
@ -67,16 +61,4 @@ public class BaseController {
|
|||
ModelAndView mav = new ModelAndView("login/denied");
|
||||
return mav;
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
public ModelAndView goMyInfo(@AuthenticationPrincipal UserInfo loginUser) {
|
||||
ModelAndView mav = new ModelAndView("user/myInfo");
|
||||
mav.addObject("loginUser", loginUser);
|
||||
if(!loginUser.getUserRole().contains("ADMIN")){
|
||||
CategoryRole categoryRole = new CategoryRole();
|
||||
categoryRole.setUserSeq(loginUser.getUserSeq());
|
||||
mav.addObject("categorySeqList", categoryRoleService.selectCategorySeqListToUser(categoryRole));
|
||||
}
|
||||
return mav;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.dbnt.kcgfilemanager.controller;
|
||||
|
||||
import com.dbnt.kcgfilemanager.model.CategoryRole;
|
||||
import com.dbnt.kcgfilemanager.model.UserInfo;
|
||||
import com.dbnt.kcgfilemanager.service.CategoryRoleService;
|
||||
import com.dbnt.kcgfilemanager.service.UserInfoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/info")
|
||||
public class InfoController {
|
||||
|
||||
private final CategoryRoleService categoryRoleService;
|
||||
private final UserInfoService userInfoService;
|
||||
|
||||
@GetMapping("/myInfo")
|
||||
public ModelAndView myInfo(@AuthenticationPrincipal UserInfo loginUser) {
|
||||
ModelAndView mav = new ModelAndView("user/myInfo");
|
||||
mav.addObject("loginUser", loginUser);
|
||||
if(!loginUser.getUserRole().contains("ADMIN")){
|
||||
CategoryRole categoryRole = new CategoryRole();
|
||||
categoryRole.setUserSeq(loginUser.getUserSeq());
|
||||
mav.addObject("categorySeqList", categoryRoleService.selectCategorySeqListToUser(categoryRole));
|
||||
}
|
||||
return mav;
|
||||
}
|
||||
|
||||
@PutMapping("/passwordModify")
|
||||
public String passwordModify(@AuthenticationPrincipal UserInfo loginUser, UserInfo modifyInfo){
|
||||
return userInfoService.updatePassword(loginUser, modifyInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,8 @@ public class UserInfo extends BaseModel implements UserDetails{
|
|||
@Column(name = "USER_STATUS")
|
||||
private String userStatus;
|
||||
|
||||
@Transient
|
||||
private String modifyPassword;
|
||||
@Transient
|
||||
private String positionName;
|
||||
@Transient
|
||||
|
|
|
|||
|
|
@ -39,6 +39,17 @@ public class UserInfoService implements UserDetailsService {
|
|||
return targetUserInfo.getUserId();
|
||||
}
|
||||
|
||||
public String updatePassword(UserInfo loginUser, UserInfo modifyInfo){
|
||||
Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder();
|
||||
if(passwordEncoder.matches(modifyInfo.getPassword(), loginUser.getPassword())){
|
||||
loginUser.setPassword(convertPassword(modifyInfo.getModifyPassword()));
|
||||
userInfoRepository.save(loginUser);
|
||||
return "OK";
|
||||
}else{
|
||||
return "passwordNotMatch";
|
||||
}
|
||||
}
|
||||
|
||||
private String convertPassword(String password){
|
||||
Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder();
|
||||
return passwordEncoder.encode(password);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,62 @@ $(document).on('click', '#moveRightBtn', function (){
|
|||
$(document).on('click', '#moveLeftBtn', function (){
|
||||
moveCategorySelectBody(-1);
|
||||
})
|
||||
$(document).on('click', '#savePasswordBtn', function (){
|
||||
if(passwordCheck()){
|
||||
const formData = new FormData($("#modifyPasswordForm")[0]);
|
||||
$.ajax({
|
||||
type : 'PUT',
|
||||
data : formData,
|
||||
url : "/info/passwordModify",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success : function(result) {
|
||||
if(result==="OK"){
|
||||
alert("수정되었습니다.");
|
||||
$("#passwordModifyModal").find(".btn-close").click();
|
||||
}else if(result==="passwordNotMatch"){
|
||||
alert("현재 비밀번호가 맞지 않습니다.");
|
||||
}
|
||||
},
|
||||
error : function(xhr, status) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function passwordCheck(){
|
||||
let returnFlag = true;
|
||||
const password = $("#password");
|
||||
const modifyPassword =$("#modifyPassword");
|
||||
const passwordConfirm = $("#passwordConfirm");
|
||||
if(!password.val()){
|
||||
alert("비밀번호를 입력해주세요.");
|
||||
returnFlag = false;
|
||||
}
|
||||
if(!modifyPassword.val()){
|
||||
alert("새 비밀번호를 입력해주세요.");
|
||||
returnFlag = false;
|
||||
}
|
||||
if(!passwordConfirm.val()){
|
||||
alert("비밀번호 확인을 입력해주세요.");
|
||||
returnFlag = false;
|
||||
}
|
||||
if(returnFlag){
|
||||
const passwordReg = /^(?=.*[a-zA-z])(?=.*[0-9])(?=.*[$`~!@$!%*#^?&\\(\\)\-_=+]).{8,16}$/;
|
||||
if(!passwordReg.test(modifyPassword.val())){
|
||||
alert("비밀번호 조건이 맞지 않습니다.")
|
||||
returnFlag = false;
|
||||
}else{
|
||||
if(modifyPassword.val() !== passwordConfirm.val()){
|
||||
alert("비밀번호가 같지 않습니다.");
|
||||
returnFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnFlag;
|
||||
|
||||
}
|
||||
|
||||
function moveCategorySelectBody(direction){
|
||||
const categorySelectBody = $("#categorySelectBody");
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
|
||||
<div class="p-3">
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-auto"><button type="button" class="btn btn-warning" id="moveLeftBtn"><i class="bi bi-arrow-left"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-warning" id="moveRightBtn"><i class="bi bi-arrow-right"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-info" id="moveLeftBtn"><i class="bi bi-arrow-left"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-info" id="moveRightBtn"><i class="bi bi-arrow-right"></i></button></div>
|
||||
</div>
|
||||
<div class="row overflow-auto flex-nowrap" id="categorySelectBody">
|
||||
<th:block th:each="depth1:${session.categoryList}">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<!--<span class="fs-4">해양경찰청 파일관리 시스템</span>-->
|
||||
</a>
|
||||
<ul class="nav nav-pills" sec:authorize="isAuthenticated()">
|
||||
<li class="nav-item"><a href="/info" class="nav-link">개인정보</a></li>
|
||||
<li class="nav-item"><a href="/info/myInfo" class="nav-link">개인정보</a></li>
|
||||
<li class="nav-item"><a href="/logout" class="nav-link">로그아웃</a></li>
|
||||
</ul>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
<div class="col-auto"><h4>개인정보</h4></div>
|
||||
<div class="col-auto">
|
||||
<th:block th:if="${!#strings.contains(loginUser.userRole,'ADMIN')}">
|
||||
<button class="btn btn-success"> 요청 현황</button>
|
||||
<button class="btn btn-warning"> 수정 요청</button>
|
||||
<button class="btn btn-success mb-2"> 요청 현황</button>
|
||||
<button class="btn btn-warning mb-2"> 수정 요청</button>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -70,19 +70,24 @@
|
|||
<input type="text" readonly class="form-control-plaintext" id="createDate" th:value="${#temporals.format(loginUser.createDate, 'yyyy-MM-dd')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row justify-content-center">
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-warning" id="passwordModifyBtn" data-bs-toggle="modal" data-bs-target="#passwordModifyModal">비밀번호 변경</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:if="${!#strings.contains(loginUser.userRole,'ADMIN')}">
|
||||
<div class="col-8">
|
||||
<h5 class="ps-3">권한정보</h5>
|
||||
<h5 class="ps-3">작성 권한</h5>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="p-3">
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-auto"><button type="button" class="btn btn-warning" id="moveLeftBtn"><i class="bi bi-arrow-left"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-warning" id="moveRightBtn"><i class="bi bi-arrow-right"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-info" id="moveLeftBtn"><i class="bi bi-arrow-left"></i></button></div>
|
||||
<div class="col-auto"><button type="button" class="btn btn-info" id="moveRightBtn"><i class="bi bi-arrow-right"></i></button></div>
|
||||
</div>
|
||||
<div class="row overflow-auto flex-nowrap" id="categorySelectBody">
|
||||
<th:block th:each="depth1:${session.categoryList}">
|
||||
|
|
@ -110,27 +115,6 @@
|
|||
</th:block>
|
||||
</th:block>
|
||||
</th:block>
|
||||
<!--<th:block th:each="depth2:${depth1.childCategoryList}">
|
||||
<tr th:classappend="${#lists.contains(categorySeqList, depth2.categorySeq)}?'bg-success bg-opacity-25':''">
|
||||
<td th:text="${depth2.categoryName}"></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<th:block th:each="depth3:${depth2.childCategoryList}">
|
||||
<tr th:classappend="${#lists.contains(categorySeqList, depth3.categorySeq)}?'bg-success bg-opacity-25':''">
|
||||
<td></td>
|
||||
<td th:text="${depth3.categoryName}"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<th:block th:each="depth4:${depth3.childCategoryList}">
|
||||
<tr th:classappend="${#lists.contains(categorySeqList, depth4.categorySeq)}?'bg-success bg-opacity-25':''">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td th:text="${depth4.categoryName}"></td>
|
||||
</tr>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</th:block>-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -146,5 +130,41 @@
|
|||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<div class="modal fade" id="passwordModifyModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="passwordModifyModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="passwordModifyModalLabel">비밀번호 변경</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body mx-4">
|
||||
<form th:action="@{/info/passwordModify}" method="post" id="modifyPasswordForm">
|
||||
<div class="mb-3 row">
|
||||
<label for="password" class="col-sm-4 col-form-label text-end">현재 비밀번호</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="password" class="form-control" id="password" name="password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="modifyPassword" class="col-sm-4 col-form-label text-end">새 비밀번호</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="password" class="form-control" id="modifyPassword" name="modifyPassword">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="passwordConfirm" class="col-sm-4 col-form-label text-end">새 비밀번호 확인</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="password" class="form-control" id="passwordConfirm">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
|
||||
<button type="button" class="btn btn-primary" id="savePasswordBtn">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
||||
Loading…
Reference in New Issue