2024. 10. 9. 18:19ㆍSpring
오늘은 Interceptor를 생성하여 일부 기능은 조건에 부합하는 사용자만이 이용할 수 있도록 제한을 걸어볼거다.
인터셉터가 필요한 이유
ex) 로그인 필요한 컨트롤러 함수에는 같은 코드를 일괄 적용 가능.
if(session.getAttribute("login") == null) {
return "redirect:/member/login";
}
그러나, 컨트롤러 함수마다 반환형이 서로 다르고
HttpSession 을 매개변수로 추가해줘야 하기 때문에 번거롭다.
메뉴의 개수가 늘어날수록 작업은 점점 더 번거로워지기 때문에
이 부분을 담당할 인터셉터가 필요하다.
Handle | 컨트롤러의 실행함수 |
PreHandle | 컨트롤러 실행하기 전에 작동하는 것 |
PostHandle | 컨트롤러가 끝나고 jsp로 넘어가기 전에 실행 |
Aftercompletion | 모든 것을 완료하기 직전 |
LoginInterceptor
로그인이 되어 있는지 판별
<로그인 인터셉터를 적용할 수 있는 곳>
마이페이지 / 게시글 작성 / 로그아웃 등
참고 > 스프링 4.0에서는 exnteds HandlerInterceptorAdapter
스프링 5에서는 implements HandlerInterceptor
HandlerInterceptor 는 인터페이스이지만, 내부함수가 default 키워드로 처리되어 있다.
인터페이스에서 default 함수는 바디를 가질 수 있다.
미구현된 메서드만 구현하면 된다.
추상 메서드가 아니라서 모든 메서드를 의무적으로 오버라이딩 할 필요는 없다.
PreHandle
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoginInterceptor implements HandlerInterceptor {
// PreHandle : 요청이 컨트롤러에 도착하기 전에 요청을 가로채서 작업을 수행
// 반환값에 따라 예정된 내용을 그대로 처리할지, 다른 내용을 수행할지 결정한다
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("1. PreHandle");
HttpSession session = request.getSession();
String url = request.getRequestURL().toString();
System.out.println("url : " + url);
if(session.getAttribute("login") == null) { // 만약 세션에 로그인이 없으면
String cpath = request.getContextPath();
response.sendRedirect(cpath + "/member/login?url=" + url);
System.out.println("로그인 상태가 아니므로, 로그인 페이지로 이동합니다.\n");
return false; // 진행 중지
// 진행 중지되고 나서는 login 페이지로 이동
}
return true;
}
PostHandle
// 컨트롤러의 처리가 끝났고, jsp 로 넘어가기전에 작동한다
// jsp로 forword 가 이루어지기 전에, request, cookie, session 등에서 필요한 값을 확인하고 판별하여
// ModelAndView 를 이용하여 특정 데이터를 넣어주는데 활용할 수 있다
// header.jsp 를 사용할수도 있으나, 모든 페이지에 영향을 주기 때문에 일부페이지에만 적용하기 쉽지않다 (== 그래서 PostHandle 을 쓰자!)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView mav) throws Exception {
System.out.println("2. postHandle");
mav.addObject("test1", "Hello, Interceptor");
}
AfterCompletion
// 사용자에게 jsp의 화면이 모두 전달되고, 응답이 완료된 후에 작동함
// 만약, 예외가 발생한다면 로그에 기록하거나 알림을 처리할 수도 있다.
// afterCompletion 대신에 사용할 수 있는 것
// 1) @ExceptionHandler, @ControllerAdvice 는 예외를 처리하는데에 특화되어있음
// 2) Log4j 와 같은 로그 라이브러리도 있다
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("3. afterCompletion");
}
}
AdminInterceptor
관리자 인터셉터, 관리자의 로그인이 적용되어있는지 판별한다.
<관리자로 로그인이 되어있는 상태> 계속 진행
<관리자로 로그인이 되어있지 않음> alert.jsp 로 넘겨서 경고창 띄워주고 대문페이지로 리다이렉트하기
유의할 점
AdminInterceptor 도 spring bean 으로 등록해줘야한다.
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import com.itbank.model.MemberDTO;
public class AdminInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("1. 관리자 계정 로그인 확인용 : preHandle");
HttpSession session = request.getSession();
MemberDTO dto = (MemberDTO) session.getAttribute("login");
if(dto == null || dto.getUserid().equals("admin") == false) {
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/member/alert2.jsp");
request.setAttribute("url", "/");
request.setAttribute("msg", "관리자 계정만 접근가능");
rd.forward(request, response);
return false;
}
return true;
}
}
코드 풀이
로그인이 되어있지 않거나(dto == null) , 로그인된 계정의 userid 가 admin 이 아니라면
-> if(dto == null || dto.getUserid().equals("admin") == false) {
alert2.jsp 로 보낸다
-> RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/member/alert2.jsp");
alert2 에서 '관리자 계정만 접근가능' 이라는 경고창을 보여주고, alert 을 확인했다면 대문페이지로 보낸다
-> request.setAttribute("url", "/");
request.setAttribute("msg", "관리자 계정만 접근가능");
alert2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../header.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script>
const url = '${url}'
const msg = '${msg}'
const cpath = '${cpath}'
if(url == '') {
alert('실패')
location.href = cpath
}
else {
alert(msg)
location.href = cpath + url
}
</script>
</body>
</html>
인터셉터를 작성은 웬만하면 개발 마지막 단계에서 진행해야 한다.
개발 도중에 진행해버리면 기능 테스트를 할때 너무 불편하기도 하고 비효율적이다.
사전에 코드를 작성하면서 인터셉터를 어느 곳에 적용시킬지 생각을 하며 개발을 하면 나중에
인터셉터를 만들어 줄때 훨씬 수월해질 것 같다.
'Spring' 카테고리의 다른 글
[Spring] FileComponent (1) | 2024.10.09 |
---|---|
[Spring] annotaion (1) | 2024.10.09 |
[Spring] mybatis mapper (4) | 2024.10.09 |
[Spring] HashComponent (1) | 2024.10.09 |
[Spring] 스프링 시작하기 (1) | 2024.10.09 |