본문 바로가기

Spring 수업 정리

Spring 8일

● 글을 생성할 때 본인의 닉네임이 들어갈 수 있도록 설정.

<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