티스토리 뷰

필터는 서블릿이 제공하는 기능

인터셉터는 스프링이 제공하는 기능이다.

 

먼저 필터를 사용해봤다.

1)로그필터

package hello.login.web.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;

@Slf4j
public class LogFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("log filter init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("log filter doFilter");
        //1. ServletRequest는 HttpServletRequest의 부모이다 먼저 치환해서 사용해야 한다.
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        String uri = httpRequest.getRequestURI();
        String uuid = UUID.randomUUID().toString();

        //2. chain.doFilter를 사용하지 않으면 작동하지 않는다. 또한 WebConfig에 해당 filter를 등록해야한다.
        try{
            log.info("REQUEST [{}][{}]", uuid, uri);
            chain.doFilter(request,response);

        }catch (Exception e){
            throw e;
        }finally {
            log.info("RESPONSE [{}][{}]", uuid, uri);
        }


    }

    @Override
    public void destroy() {
        log.info("log filter destroy");
    }
}

 

2)로그인 필터 (로그인한 사용자만 사용할 수 있는 기능, 페이지가 있는 경우의 처리 whiteList는 비로그인 사용자도 들어갈 수 있는 경로들)

package hello.login.web.filter;

import hello.login.web.session.SessionConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.PatternMatchUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Slf4j
public class LoginCheckFilter implements Filter {

    private static final String[] whiteList = {"/","/members/add","/login","/logout","/css/*"};

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();

        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try {
            log.info("인증 체크 필터 시작{}", requestURI);

            if(isLoginCheckPath(requestURI)){
                log.info("인증 체크 로직 실행 {}", requestURI);
                HttpSession session = httpRequest.getSession(false);

                if(session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null){
                    log.info("미인증 사용자 요청 {}", requestURI);
                    //로그인으로 redirect
                    httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
                    return; //여기가 중요, 미인증 사용자는 다음으로 진행하지 않고 끝
                }
            }
            chain.doFilter(request,response);
        }catch (Exception e){
            throw  e; //예외 로깅 가능 하지만, 톰캣까지 예외를 보내주어야함
        }finally {
            log.info("인증 체크 필터 종료 {}" , requestURI);
        }

    }

    /*
    * 화이트 리스트의 경우 인증 체크 X
    **/
    private boolean isLoginCheckPath(String requestURI){
        //requestURI가 whiteList에 들어있으면 true 아니면 false를 반환하지만 없는 것을 찾기에 !를 붙여준다.
        return !PatternMatchUtils.simpleMatch(whiteList,requestURI);
    }
}

 

3) WebConfig 사용 (filter를 만든 것 만으로는 움직이지 않는다. 이곳에서 bean등록 및 순서를 정해줘야한다.)

package hello.login;

import hello.login.web.filter.LogFilter;
import hello.login.web.filter.LoginCheckFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean logFilter(){
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter()); //만든 필터를 넣는다.
        filterRegistrationBean.setOrder(1); //작동 순서를 정한다.
        filterRegistrationBean.addUrlPatterns("/*"); //어떤 url일 때에 작동할지를 적는다.

        return filterRegistrationBean;

    }

    @Bean
    public FilterRegistrationBean loginFilter(){
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LoginCheckFilter()); //만든 필터를 넣는다.
        filterRegistrationBean.setOrder(2); //작동 순서를 정한다.
        filterRegistrationBean.addUrlPatterns("/*"); //어떤 url일 때에 작동할지를 적는다.

        return filterRegistrationBean;

    }

}

 

4) 비로그인 사용자는 결국 /login으로 향하게 된다. 이때 리다이렉트 처리를 해준다.

로그인컨트롤러

@PostMapping("/login")
    public String loginV04(@Valid @ModelAttribute LoginForm loginForm, BindingResult bindingResult, HttpServletRequest request
            , @RequestParam(defaultValue = "/")String redirectURL){

        if(bindingResult.hasErrors()){
            return "login/loginForm";
        }
        Member member = loginService.login(loginForm.getLoginId(), loginForm.getPassword());

        if(member == null) {
            bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
            return "login/loginForm";
        }
        //로그인 성공 처리
        //세션이 있으면 있는 세션 반환, 없으면 신규 세션을 생성
        HttpSession session = request.getSession(); //default: true
        //true는 세션이 있으면 기존 세션을 반환, 세션이 없으면 새로운 세션을 생성해서 반환한다.
        //false는 세션이 있으면 기존 세션을 반환한다.
        //세션이 없으면 새로운 세션을 생성하지 않는다. null을 반환한다.

        session.setAttribute(SessionConst.LOGIN_MEMBER, member);

        return "redirect:" + redirectURL;
    }

 

 

추가적으로 필터는 리퀘스트와 리스폰스를 바꿔서 사용할 수도 있다.

'dev_공부일지 > spring boot + intelliJ' 카테고리의 다른 글

ArgumentResolver 직접 어노테이션 만들기  (0) 2023.11.29
인터셉터 1  (1) 2023.11.22
session timeout  (0) 2023.06.06
session  (0) 2023.06.06
Cookie를 이용한 로그인 (1)  (0) 2023.05.27
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함