개발 무지렁이

[Servlet] 사전/사후 처리를 위한 Filter 인터페이스 본문

Backend/Servlet & JSP

[Servlet] 사전/사후 처리를 위한 Filter 인터페이스

Gaejirang-e 2023. 4. 25. 19:04

𐁍 Filter 인터페이스
@WebFilter(urlPatterns = {"/[pattern]"} implements Filter

DispatcherServlet으로 요청(request)이 가기 전 가로챈다.

(⚠️ Servlet보다 앞단에 놓인다)
(⚠️ Filter를 여러개 놓을 수 있는데, 가장 먼저 사전처리Filter가 가장 나중에 사후처리된다.)
(🩻 스프링 시큐리티(Spring Security)는 내부적으로 Filter로 동작한다)

🎯 목적:
인코딩(Encoding) 처리, 인증 여부 체크, 로깅(Logging)

🦔 인증 여부 체크 코드

🦉 HttpSession에 저장된 정보가 있는지 체크
  HttpServletRequest req = (HttpServletRequest)requestl

  HttpSession session = req.getSession();
  if(session.getAttribute("[???]") == null) {
      HttpServletResponse res = (HttpServletResponse) response;
      res.sendRedirect("로그인 폼으로 이동");
      return;
  }
𖠃 Filter 구현객체 동작 원리, init( ) > doFilter( ) > destroy( )
🪆 doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

FilterChain:
여러개의 Filter들은 순차적으로 연결되어 FilterChain을 형성한다.
Filter들은 원하는 작업을 수행한 후 FilterChaindoFilter() 메서드를 호출하여
다음 Filter로 제어를 넘긴다.

⚠️ doFilter() 메서드의 3번째 인자를 주지 않으면, 해당 요청(request)은 다음 Filter로 진행하지 않는다.

📜 EncodingFilter.java

  @WebFilter(urlPatterns = {"/encodingResult.jsp", "/enc"})
  public class EncodingFilter implements Filter {
      public EncodingFilter() {
          System.out.println("EncodingFilter constructor call");
      }

    //🪆 [default method] filter나 servlet이 초기화될때 제공되는 설정정보를 담고있다.
      public void init(FilterConfig fConfig) throws ServletException {
          System.out.println("EncodingFilter init call");
      }

    //🪆 [default method] filter 작업 처리
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          System.out.println("사전처리입니다...");
          request.setCharacterEncoding("UTF-8");
          chain.doFilter(request, response);
          System.out.println("사후처리입니다...");
      }

      //🪆 [default method] destroy
      public void destroy() {
          System.out.println("EncodingFilter destroy call");
      }
  }

📜 EncodingServlet.java

  @WebServlet("/enc")
  public class EncodingServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
          String name = request.getParamter("name");
          System.out.println("name: " + name);
      }
  }

📜 encodingResult.jsp

  <%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8">
      <title>Insert title here</title>
    </head>  
    <body>
      <h2>결과: ${param.name}</h2>
    </body>  
  </html>

📜 index.jsp

  <%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8">
      <title>Insert title here</title>
    </head>
    <body>
      <h3>~.jsp 이동</h3>
      <form method="post" action="encodingResult.jsp">
        이름: <input type="text" name="name">
        <input type="submit" value="전송">
      </form>  
    </body>  
  </html>  
🦉 코드 설명

form 태그의 action 속성값에 EncodingFilter.java의 urlPatterns와 동일한 url을 넣어주면
Servlet(EncodingServlet.java)로 가기 전에,
Filter(EncodingFilter.java)가로채서 처리한다.

🏓 BadRequestFilter 구현


📜 BadRequestFilter.java

  @WebFilter(urlPatterns = "/*")
public class BadRequestFilter implements Filter{
    private Logger work_log = Logger.getLogger("work"); 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter init call");
    }


    @Override
    public void destroy() {
        System.out.println("Filter destroy call");
    }

    // 인코딩 처리 및 경로 지정
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
              throws IOException, ServletException {
          //클라이언트가 전송한 데이터를 UTF-8로 인코딩하도록 서버에게 지시
          request.setCharacterEncoding("UTF-8");

          //HttpServletRequst의 내장메서드 getRequestURI()를 통한 URI 정보 가져오기
          String uri = ((HttpServletRequest)request).getRequestURI();
          work_log.debug("doFilter----"+uri);

          // URI 맨 뒤의 '/'부터 끝까지 자르기
          String path = uri.substring(uri.lastIndexOf("/"));
          work_log.debug("doFilter----"+path);
          if(path.equals("/")) {
              //새로운 request, response를 생성하여 이동(정보손실)
              ((HttpServletResponse)response).sendRedirect("main.bit");
              return;
          }

          chain.doFilter(request, response);
      }
  }  
🦉 코드 설명

웹 애플리케이션에서 클라이언트의 요청을 처리하기 위해 Servlet을 사용하는 경우,
클라이언트의 요청이 ServeltReqeust객체로 표현된다.
때문에, HTTP 프로토콜에 특화된 메서드를 사용하기 위해 HttpServletRequest로 형변환해서 사용한다.

HttpServletRequest의 🦘내장메서드 .getRequestURI()를 호출해 HTTP 요청의 URI 정보를 가져올 수 있다.

🧸 URI: 리소스를 식별하고 위치정보를 담고있는 통합 자원 식별자(Uniform Resource Identifier)를 말한다.
Comments