today_is
[ spring ] Interceptor 본문
오늘의 목표
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
package com.itbank.interceptor;
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 으로 등록해줘야한다 !
package com.itbank.interceptor;
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>
study_review
항상 로그인이 되어있지 않다면 login페이지로 리다이렉트 하도록 코드를 복붙해서 추가했었는데
인터셉터를 이용하면 현재 상태에 따라, 사용자에게 안내할 수 있어서 좀 더 편리한것 같다
그렇지만 인터셉터는 개발 도중에 진행하는 것이 비효율적이라고 한다.
아직 기능이 제대로 구현되지 않은채로 인터셉터를 걸어버리면
테스트를 진행할때 너무 불편하기 때문이다.
그래서 꼭 개발 마지막 단계에 진행해야한다.
미리 인터셉터를 어디에 적용시킬지 생각하면서 개발에 임하면
나중에 수월할 것 같다는 생각이 든다 !
'spring' 카테고리의 다른 글
[ spring ] FileComponent , 다중 파일업로드 (0) | 2024.01.04 |
---|---|
[ spring ] 어노테이션 문법정리 (0) | 2024.01.02 |
[ spring ] mybatis mapper 이용 (0) | 2023.12.28 |
[ spring ] HashComponent 이용하기 (0) | 2023.12.28 |
[ spring ] 스프링과의 첫만남 (0) | 2023.12.27 |