● 글을 생성할 때 본인의 닉네임이 들어갈 수 있도록 설정.
<sec:authentication property="principal.uvo.nickName" var="authNick"/>
<div class="mb-3">
<label for="w" class="form-label">writer</label> <input type="text"
class="form-control" id="w" name="writer" value="${authNick }" readonly="readonly">
</div>
● 로그인을 하지않으면 댓글을 작성하는 창이 나오지않도록 sec:authorize로 권한이 있을때만 띄우게만듬.
sec:authentication로 닉네임을 가져와서 작성자는 본인의 닉네임으로 설정
<sec:authorize access="isAuthenticated()">
<div class="input-group mb-3">
<span class="input-group-text" id="cmtWriter">
<sec:authentication property="principal.uvo.nickName" var="authNick"/>
${authNick }
</span>
<input type="text" id="cmtText" class="form-control" placeholder="Add Comment" aria-label="Comment" aria-describedby="basic-addon1">
<button type="button" id="cmtAddBtn" class="btn btn-outline-success">post</button>
<c:set value="${authNick }" var="nick" />
</div>
</sec:authorize>
c:set은 로그인하지않아도 자바스크립트 authNick을 인지할 수 있도록 설정.
● 댓글에서 작성자의 닉네임과 본인의 닉네임이 다르면 수정, 삭제버튼이 사라지도록 구현 (본인만 수정/삭제할 수 있게)
<script type="text/javascript">
let authNick = `<c:out value ="${nick}" />`;
console.log(authNick);
</script>
일단 로그인한 아이디의 닉네임을 벨류로받아서 스크립트에서 인식할 수 있도록함.
if( authNick == cvo.writer){
li += `<div class="d-grid gap-2 d-md-flex justify-content-md-end">`;
li += `<button type="button" data-cno=${cvo.cno} class="btn btn-outline-warning btn-sm mod" data-bs-toggle="modal" data-bs-target="#myModal">%</button>`;
li += `<button type="button" data-cno=${cvo.cno} class="btn btn-outline-danger btn-sm del">X</button>`;
li += `</div>`;
}
자바스크립트 버튼부분을에 받아온 authNick과 작성자가 같은지 확인해서 같으면 버튼을 보여줄 수 있도록 수정.
● ADMIN 권한을 가지고 있는 유저에게 회원리스트 볼 수 있게 구현
<c:if test="${auths.stream().anyMatch(authVO -> authVO.auth.equals('ROLE_ADMIN')).get()}">
<li class="nav-item">
<a class="nav-link text-danger" href="#">회원리스트(ADMIN) </a>
</li>
</c:if>
header부분에 ADMIN만 가능하도록 만들어주고 권한은 DB에서 넣어주도록함.
insert into auth(email,auth) values('1111@naver.com','ROLE_ADMIN');
● list.jsp만들어서 유저리스트 화면 구성
<h1>UserList Page...</h1>
<hr>
<div class="row row-cols-1 row-cols-md-3 g-4">
<c:forEach items="${userList }" var="uvo">
<div class="col">
<div class="card">
<img src="/resources/image/사람2.png" class="card-img-top" alt="...">
<div class="card-body">
<h4 class="card-title">${uvo.email }</h4>
<c:forEach items="${uvo.authList }" var="avo">
<span class="badge text-bg-info">${avo.auth }</span>
</c:forEach>
<br><br> <p class="card-text">가입일 : ${uvo.regDate }</p>
<p>마지막 로그인 : ${uvo.lastLogin }</p>
</div>
</div>
</div>
</c:forEach>
</div>
<br> <a href="/" class="btn btn-primary">돌아가기</a>
● getMapping해서 UserVO의 객체의 리스트를 서비스, 다오 , 매퍼에 연결해서 가져와서 모델을이용해 addAttribute해서
userList를 보낼 수 있도록함
@GetMapping("/list")
public void list(Model m) {
List<UserVO> userList = usv.getList();
m.addAttribute("userList", userList);
}
서비스구현에서는 UserVO 객체의 AuthList 정보도 받아야하기때문에 list를 가져와서 for문으로 authList도 가져올 수 있도록 함.
@Override
public List<UserVO> getList() {
List<UserVO> userList = udao.getList();
for(UserVO uvo : userList) {
uvo.setAuthList(udao.selectAuths(uvo.getEmail()));
}
return userList;
}
<select id="selectAuths" resultType="com.ezen.spring.domain.AuthVO">
select * from auth where email = #{email}
</select>
<select id="getList" resultType="com.ezen.spring.domain.UserVO">
select * from user order by reg_date desc
</select>
● 로그인한 유저의 정보를 받아와서 수정할 수 있는 기능을 구현하기위해 화면생성
<sec:authentication property="principal.uvo" var="uvo"/>
<form action="/user/modify" method="post">
<input type="hidden" name="email" value="${uvo.email }">
<div class="card mb-3" style="max-width: 540px;">
<div class="row g-0">
<div class="col-md-4">
<img src="/resources/image/사람2.png" class="img-fluid rounded-start"
alt="...">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">
<input type="text" id="n" name="nickName" value="${uvo.nickName }">
<input type="text" id="p" name="pwd" placeholder="password...">
</h5>
<c:forEach items="${uvo.authList }" var="avo">
<span class="badge text-bg-info">${avo.auth }</span>
</c:forEach>
<p class="card-text">가입일 : ${uvo.regDate }</p>
<p class="card-text">
<small class="text-body-secondary">마지막 로그인 :
${uvo.lastLogin }</small>
</p>
<button type="submit" class = "btn btn-primary btn-sm">modify</button>
<a href="/user/delete"><button type="button" class = "btn btn-danger btn-sm">delete</button></a>
</div>
</div>
</div>
</div>
</form>
로그인한 정보를 받아오기위해
<sec:authentication property="principal.uvo" var="uvo"/> 를 사용해서 uvo에 정보를 받아주고
post로 email의 정보까지 보내기위해 input hidden으로 숨겨서 email 정보를 보낼 수 있도록 해줌.
삭제버튼은 /user/delete로 보내서 컨트롤러에서 따로 구현
● modify.jsp에서 post된 uvo 객체를 받아서 잘들어오는지 확인하고 수정시 비밀번호를 입력하지않았으면 비밀번호를 제외하고 업데이트진행, 비밀번호를 입력해서 수정했다면 닉네임과 비밀번호 둘다 수정할 수 있도록 설정.
업데이트는 서비스 > 다오 > 매퍼로 연결해서 구현만하면됨 코드생략
수정이 완료되면 보내줄 메세지를 담을 RedirectAttribute객체를 받아서 메세지를 addFlashAttribute로 1회성으로 날려줌.
로그아웃 메서드에서 필요한 리퀘스트와 리스폰스 받아주어야함.
@GetMapping("/modify")
public void modify() {}
@PostMapping("/modify")
public String modify(UserVO uvo, HttpServletRequest request, HttpServletResponse responce, RedirectAttributes re) {
log.info(">>> modfiy uvo >> {}" ,uvo);
int isOk = -1;
if(uvo.getPwd().isEmpty() || uvo.getPwd().length() == 0) {
// 비번 없이 업데이트 진행
isOk = usv.modifyPwdEmpty(uvo);
}else {
// 비번 암호화 후 업데이트 진행
uvo.setPwd(bcEncoder.encode(uvo.getPwd()));
isOk = usv.modify(uvo);
}
// 로그아웃 => index로 돌아가기
logout(request, responce);
if(isOk > 0 ) {
re.addFlashAttribute("modify_msg", "ok");
} else {
re.addFlashAttribute("modify_msg", "fail");
}
return "redirect:/";
}
● 로그아웃 구현을 위해 로그아웃 메서드 생성
private void logout(HttpServletRequest request, HttpServletResponse responce) {
// 내가 로그인 한 시큐리티의 authentication 객체
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
new SecurityContextLogoutHandler().logout(request, responce, authentication);
}
● Principal객체에 로그인정보가 담겨있으니.getName으로 id인 email을 받아와주고 받아온 email을 넣어서 remove
서비스> 다오> 매퍼로 연결.
똑같이 삭제가 완료됐을 때 메세지를 1회성으로 addFlashAttribute로 날려주고, 로그아웃메서드를 이용해서 로그아웃.
@GetMapping("/user/delete")
public String delete(HttpServletRequest request, HttpServletResponse responce, Principal principal, RedirectAttributes re) {
log.info(principal.toString());
String email = principal.getName();
int isOk = usv.remove(email);
if(isOk > 0 ) {
re.addFlashAttribute("remove_msg", "ok");
} else {
re.addFlashAttribute("remove_msg", "fail");
}
logout(request,responce);
return "redirect:/";
}
● Service에서는 User와 Auth 테이블은 외래키로 엮여있기때문에 삭제할때 auth부터 삭제해주고 user를 삭제해주어야함.
@Override
public int remove(String email) {
int isOk = udao.removeAuth(email);
return udao.remove(email);
}
● 메인페이지인 index.jsp에서 스크립트를 열고 수정,삭제 완료/실패 메세지를 받아주면됨
<script>
let modify_msg = `<c:out value="${modify_msg}" />`;
console.log(modify_msg);
if(modify_msg == 'ok'){
alert("회원정보가 수정되었습니다. 다시로그인해주세요.");
}
if(modify_msg == 'fail'){
alert("회원정보수정이 실패되었습니다. 다시시도해주세요.");
}
let remove_msg = `<c:out value="${remove_msg}" />`;
console.log(remove_msg);
if(remove_msg == 'ok'){
alert("회원 탈퇴가 완료되었습니다. 안녕히가세요.");
}
if(remove_msg == 'fail'){
alert("회원탈퇴가 실패되었습니다. 다시시도해주세요.");
}
</script>
404에러 페이지 설정
● exception 패키지를 만들고 안에 CommonExceptionAdvice 생성
● CommonExceptionAdvice를 읽을 수 있게 ServletConfiguration와 WebConfig 수정
@ComponentScan(basePackages = {"com.ezen.spring.controller","com.ezen.spring.service","com.ezen.spring.handler","com.ezen.spring.security","com.ezen.spring.exception"})
"com.ezen.spring.exception" 을 넣어주고
@Override
protected void customizeRegistration(Dynamic registration) {
// 사용자 지정 익셉션 처리 설정
registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
// 파일 업로드 설정 ( 위치 설정 )
String uploadLocation = "D:\\_myProject\\_java\\_fileUpload";
int maxFileSize = 1024*1024*20; // 20MB
int maxReqSize = maxFileSize * 3;
int fileSizeThreshold = maxFileSize;
MultipartConfigElement multipartConfig = new MultipartConfigElement(uploadLocation, maxFileSize, maxReqSize, fileSizeThreshold);
registration.setMultipartConfig(multipartConfig);
}
사용자 지정 익셉션 처리 설정 registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); 추가
● CommonExceptionAdvice 구현
@Slf4j
@ControllerAdvice
public class CommonExceptionAdvice {
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handler404(NoHandlerFoundException ex, Model m) {
log.info(">>>> exception >> {} ", ex.getMessage());
m.addAttribute("exception", ex.getMessage());
return "custom404";
}
}
● custom404 화면 생성
custom404.jsp
<h1> Custom 404 Page... </h1>
<h3> <c:out value="${exception }"></c:out> </h3>
안에 원하는 헤더, 푸터 , 이미지 등등 넣어서 만들어줄 수 있음.
'Spring 수업 정리' 카테고리의 다른 글
Spring 7일 (0) | 2024.11.05 |
---|---|
Spring 6일 (3) | 2024.11.04 |
Spring 5일 (1) | 2024.11.01 |
Spring 3일차. (0) | 2024.10.30 |
Spring 1일차. (0) | 2024.10.28 |