개념
- 요청 및 응답 가로채기
- 클라이언트(브라우저)에서 서버로 들어오는 요청이나 서버에서 클라이언트로 나가는 응답 가로채서 필요한 로직 실행, 처리
- 재사용 가능한 컴포넌트
- 여러 서블릿이나 JSP에 대해 공통적으로 수행해야 하는 작업을 하나의 필터로 구현하여 재사용
- 체인(chain) 구조
- 여러 필터를 체인 구조로 연결하여 순차 실행 가능
- 각 필터는 다음 필터를 호출하거나 체인 중단 할 수 있음
필터의 라이프 사이클
- init()
- 필터가 초기화될 때 한 번 호출되고 초기화 작업 수행 가능
- doFilter()
- 클라이언트의 요청을 가로채고 필요한 작업을 수행한 후 다음 필터 또는 서블릿 호출 ⇒ 필터의 핵심 메서드
- destroy()
- 필터가 제거될 때 호출되고 리소스 해제하는 등의 정리 작업 수행 가능
인증 블로그에 필터 활용하기
필터를 활용하지 않고 인가(권한 부여) 하는 경우
- session에 sessionUser라는 값이 있는지 확인 ⇒ 로그인(인증) 체크
- 값이 없으면(로그인을 안 한 상태) 로그인 페이지로 강제 이동
- 글 쓰기, 수정, 삭제, 댓글 쓰기 등은 로그인이 되어있는 상태에서만 가능해야하기 때문에 코드 내용을 필요한 컨트롤러 내부의 메서드마다 작성해야하는 불편함 발생
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null) {
resp.sendRedirect(req.getContextPath() + "/login-form");
}- BoardController 클래스에서의 예
- 로그인 안 된 상황에서는 글쓰기 페이지 진입을 막는 코드 작성
- 수정, 삭제 등의 경우가 추가되면 각 메서드들마다 이렇게 코드를 작성해야하는 불편함 발생
@RequiredArgsConstructor
@Controller
public class BoardController {
private final HttpSession session;
@GetMapping("/")
public String index() {
return "index";
}
@GetMapping("/board/save-form")
public String saveForm() {
// 이렇게 작성하지않으면 로그인(인증)되지않은 상태에서 글쓰기가 가능하게 됨
// 글 다 적고 글쓰기 버튼 눌렀는데 로그인하라고 로그인 페이지로 넘어가버림
// 로그인 하고 왔는데 글 적어놓은거 날아가서 다시 적어야됨
// 그래서 로그인(인증) 안했으면 글쓰기 페이지 진입 못하도록 막아놓기
User sessionUser = (User) session.getAttribute("sessionUser");
if (sessionUser == null) {
throw new RuntimeException("인증되지 않음 401");
}
return "board/save-form";
}
}필터 활용
[AuthenticationFilter 클래스 - 필터 클래스]
- Filter 인터페이스 구현
- 이 필터는 클라이언트의 요청을 가로채고, 요청 처리 전에 인증 검사
- Filter import 할때는 jakarta로 해야함
- doFilter 메서드 오버라이드
- 필터의 핵심 메서드
- 요청을 가로채고 처리 수행 후 다음 필터 또는 서블릿으로 전달
- servletRequest, servletResponse 객체를 HttpServletRequest, HttpServletResponse로 다운캐스팅
- HTTP 요청과 응답에 대한 구체적인 기능 사용 가능
- HttpSession session = req.getSession()
- HttpServletRequest 객체를 통해 세션 가져옴
- 세션은 사용자와 서버 간의 상태 정보를 저장하는 공간
- User sessionUser = (User) session.getAttribute("sessionUser")
- 세션에서 로그인된 사용자 정보를 담은 sessionUser를 가져옴
- 인증 여부 검사
- sessionUser가 null이면 사용자가 로그인되지 않은 상태이므로 로그인 페이지(/login-form)로 리다이렉트
- 인증된 사용자 처리
- seeeionUser가 null이 아니면 사용자가 인증된 상태이므로 요청을 다음 필터 또는 서블릿으로 전달
package com.metacoding.authblog._core.filter;
import com.metacoding.authblog.user.User;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
public class AuthenticationFilter implements Filter {
// FilterChain : 다음 필터 호출하기 위한 매개변수
// doFilter 메서드 오버라이드 : 요청을 가로채고 처리 수행 후 다음 필터 또는 서블릿으로 전달
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("돌고 있나?");
// 다운캐스팅
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
// 리퀘스트 객체에서 세션 가져오기
HttpSession session = req.getSession();
// 세션에서 로그인된 사용자 정보를 담은 sessionUser를 가져옴
User sessionUser = (User) session.getAttribute("sessionUser");
// 인증 여부 검사
if (sessionUser == null) {
resp.sendRedirect("/login-form"); // 로그인 페이지로 리다이렉트
} else {
// 인증된 사용자 처리
filterChain.doFilter(servletRequest, servletResponse);
}
}
}[FilterConfig 클래스 - 설정 파일 생성]
- 인증 필터인 AuthenticationFilter를 특정 URL 패턴에 적용하도록 구성
- @Configuration
- Spring Framework에서 필터를 설정하고 등록하는 구성 클래스
- Spring IoC 컨테이너는 이 클래스의 빈(bean) 정의를 처리
- @Component와 @Configuration의 차이
- @Component : 간단하게 필터 등록, 자동 감지, 기본적으로 모든 요청에 대해 적용
- @Configuration : URL 패턴, 필터 순서 등 더 많은 제어와 세부 설정 가능
- @Bean
- 이 메서드가 Spring 컨테이너에 의해 관리되는 빈을 생성함을 나타냄
- addAuthFilter() 메서드는 FilterRegistrationBean을 반환하고, 반환값은 IoC 컨테이너에 등록됨
- FilterRegistrationBean rg = new FilterRegistrationBean() rg.setFilter(new AuthenticationFilter())
- FilterRegistrationBean 객체를 생성하고, AuthenticationFilter를 필터로 설정
- AuthenticationFilter는 사용자 인증을 처리하는 필터
- 필터가 적용될 URL 패턴 등록
- 주소가 /board 이거나 /user로 시작하는 모든(*) 경우에만 적용
- 이 경로에 대한 요청은 모두 AuthenticationFilter를 거침
- rg.setOrder(1)
- 필터 실행 순서 설정
- 숫자가 작을수록 우선 순위가 높아지고 1은 첫번째로 실행됨 의미
- return rg;
- 설정이 완료된 FilterRegistrationBean 반환하여 IoC 컨테이너에 등록
package com.metacoding.authblog._core.config;
import com.metacoding.authblog._core.filter.AuthenticationFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 설정 파일에는 @Configuration, 그 외 용도의 파일에는 @Component
@Configuration // @Component 포함
public class FilterConfig {
@Bean // 리턴값이 IOC에 등록됨, @Bean이 붙어있는 메소드 찾아내서 필터 장착시킴
public FilterRegistrationBean addAuthFilter() {
// FilterRegistrationBean 객체를 생성하고, AuthenticationFilter를 필터로 설정
// AuthenticationFilter는 사용자 인증을 처리하는 필터
FilterRegistrationBean rg = new FilterRegistrationBean();
rg.setFilter(new AuthenticationFilter());
// URL 패턴 등록
// 주소가 /board 이거나 /user로 시작하는 경우에만 (*은 모든)
rg.addUrlPatterns("/board/*");
rg.addUrlPatterns("/user/*");
rg.setOrder(1); // 필터 실행 순서 설정
// addAuthFilter() 메서드는 FilterRegistrationBean을 반환하고,
// 반환값은 IoC 컨테이너에 등록됨
return rg;
}
}Share article