개발진행목록/게시판 서비스
[JPA로 게시판 만들기] Spring Interceptor를 사용한 인증 체크
by o3oppp
2025. 3. 4.
스프링 인터셉터
- 서블릿 필터와 같이 웹과 관련된 공통 관심 사항을 효과적으로 해결하는 기술
- URL만 알면 로그인을 하지 않아도 여러 페이지에 접근이 가능하기 때문에, 이를 방지하기 위해 스프링 인터셉터를 사용
- 자세한 내용은 여기에 게시하였습니다.
스프링 인터셉터 흐름과 제한
정상 요청
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 // 정상 로그인 시
비적절한 요청
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 (이후 컨트롤러 호출X)
인터셉터 구현
LoginCheckInterceptor.java
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import project.post.session.SessionConst;
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("인증 체크 인터셉터 실행 {}", requestURI);
HttpSession session = request.getSession();
if(session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null){
log.info("미인증 사용자 요청");
response.sendRedirect("login?redirectURL=" + requestURI);
return false;
}
return true;
}
}
- HandlerInterceptor : 스프링 인터셉터를 사용하기 위해 해당 인터페이스를 구현
- preHandle : 컨트롤러 호출 전 호출되는 Method
- 응답값이 true이면 다음으로 진행하고, false이면 더 이상 진행하지 않음
- response.sendRedirect : 정상 로그인 후 요청한 페이지로 리다이렉션을 위함
LoginController.java
@Controller
@RequiredArgsConstructor
public class LoginController {
private final LoginService loginService;
private final SessionManager sessionManager;
@GetMapping("/login")
public String loginForm(Model model){
model.addAttribute("loginForm", new LoginForm());
return "login/loginForm";
}
@PostMapping("/login")
public String login(@Valid LoginForm loginForm, BindingResult result,
@RequestParam(defaultValue = "/") String redirectURL,
HttpServletRequest request){
if(result.hasErrors()){
return "login/loginForm";
}
Member loginMember = loginService.login(loginForm.getLoginEmail(), loginForm.getPassword());
if(loginMember == null){
result.reject("loginFail", "이메일 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
// 로그인 성공 처리
// 세션이 있으면 세션 반환, 없으면 신규 세션 생성
HttpSession session = request.getSession();
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
return "redirect:" + redirectURL; // 요청 URL로 리다이렉션
}
...
}
- login Method 내 요청 URL로 리다이렉션을 위한 코드 추가
WebConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import project.post.interceptor.LogInterceptor;
import project.post.interceptor.LoginCheckInterceptor;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/", "/login", "/logout", "/members/new", "/css/**", "/*.ico", "/error");
}
}
- WebMvcConfigurer가 제공하고는 addInterceptors()를 사용해서 인터셉터를 등록
- registry.addInterceptor(new LoginCheckInterceptor()) : 인터셉터를 등록
- order : 인터셉터의 호출 순서를 지정. 낮을수록 먼저 호출
- addPathPatterns : 인터셉터를 적용할 URL 패턴을 지정
- excludePathPatterns : 인터셉터에서 제외할 패턴을 지정
스프링 인터셉터 체인
HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터1 -> 인터셉터2 -> ... -> 컨트롤러
- 스프링 인터셉터는 체인으로 구성되는데, 중간에 인터셉터를 자유롭게 추가 가능