내가 보려고 정리하는/Spring

웹 : D.F.P으로 필터 만들어보기 : 0331

보동이용용 2023. 3. 31. 08:44
반응형

필터를 적용해보자.

필터는 2버전 3버전 모두 있어서 갈아 끼울 수 있어야한다. 액세서리라고 부르며 데코레이팅 필터 P는 뭐지 

암튼 이걸이용하여 보자

필터의 기본구조

필터역할

1. controller기준 전처리 작업(63/66라인 없애기)

2. 보안처리 (인증과 인가 기반의 접근제어 auth)

cross site script 공격 막아보자.

 

필터를 거쳐도 요청의 일부 성질들이 변경될 뿐 요청은 그대로 유지된다. 요청의 정보도 변경할 수 있지만 그에 맞는 응답결과도 알맞게 변경할 수 있다.   << 필터 : 요청과 응답에 대한 전, 후 처리 작업  >>

필터는 액세서리이기 때문에 여러개를 걸수도 있다.

이 여러개의 필터를 묶어서 FilterChain을 형성하여 사슬처럼 엮어 사용한다. 사슬은 순서를 바꾸지 못한다. 순서고정. 요청과 응답의 필터 처리 순서는 역순이다. stack메모리 구조 때문. FILO

flow Control과정에서도 사용할 수도 있다.

필터 사용 이유 : 흐름을 변경하는 역할, 사용자 인증이나 권한체크와 같은 기능 구현 (인증 auth) 


필터 생성 방법

자바x servlet의 filter(필터 최상위 객체)를 구현한다.

생성해보면 init과 destroy 메서드가 생성된다. > 서블릿의 형태이다. > 톰캣과 대화한다. > 등록한다.

톰캣에 등록할 때 필터 체인이 형성된다.

  1. Authentication Filters - 인증
  2. Logging and Auditing Filters - Log를 이곳에만 남겨서 어플리케이션은 가지지 않도록 할수있다.
  3. Image conversion Filters - 이미지를 사용용도에 맞게 알아서 변환해주는 것
  4. Data compression Filters - 요청뿐아니라 응답할때 압축하여 응답의 크기를 줄여 보낼 수 있다.
  5. Encryption Filters - 암호화 (공통키 : 양쪽이 공통적으로 약속한 키) 
  6. Tokenizing Filters - 
  7. Filters that trigger resource access events
  8. XSL/T filters
  9. Mime-type chain Filter

필터도 싱글턴으로 관리된다.

여기에 있는 라이프사이클 메서드도 한번만 실행된다. 라이프 사이클에서 로그 기록햇음

▶FirstFilter

package kr.or.ddit.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import lombok.extern.slf4j.Slf4j;

@Slf4j //롬복에서 지원하는 어노테이션
public class FirstFilter implements Filter {
	//어펜더, 로거 레이아웃
	//퍼사드 구조
//	private Logger log = LoggerFactory.getLogger(FirstFilter.class);
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//debug는 사용 못하므로 info이상의 레벨의 로거를 사용해야함.
		log.info("{} 필터가 로딩됨.", this.getClass().getSimpleName()); //메세지 아귀먼트 {}
		//어떤 필터가 로딩됐는지 알 수 있음. sysout걷어내자.

	}

	@Override            //http 없다! 상위타입
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest) request;
		
		log.info("{} 요청이 필터링됨.", req.getRequestURI());
		
		chain.doFilter(request, response); //요청과 응답의 필터의 경계

		log.info("{} 에 대한 요청으로 생성된 응답이 필터링됨.", req.getRequestURI());
	}

	@Override
	public void destroy() {
		log.info("{}필터가 소멸됨.", this.getClass().getSimpleName()); 
	}

}

로그만 기록

▶web.xml 

서블릿등록 다시 공부하자

  <filter>
  	<filter-name>FirstFilter</filter-name>
  	<filter-class>kr.or.ddit.filter.FirstFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>FirstFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

 

▶SecondFilter

무조건 웰컴페이지로 가도록 flow control

@Override            //http 없다! 상위타입
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    String uri = req.getRequestURI();
    uri = StringUtils.substringAfter(uri, req.getContextPath());
    log.info("{} 요청이 필터링됨.", uri);


    log.info("{} 에 대한 요청으로 생성된 응답이 필터링됨.", req.getRequestURI());
    //흐름을 제어하는 코드
    boolean pass = false;

    if("/".equals(uri)) {
        pass = true;
    }else if("/default.jsp".equals(uri)) {
        pass = true;
    }else if(uri.startsWith("/resources")) {
        pass = true;
    }else if(uri.startsWith("/includeee")) {
        pass = true;
    }

    if(pass) {
        chain.doFilter(request, response); //요청과 응답의 필터의 경계 //체인이 끊기면 어플리케이션이 작동을 안한다.
    }else {
        resp.sendRedirect(req.getContextPath() + "/");
    }
}

 

▶ThirdFilter

who로 파라미터 받으면 a001로 바꿔버리는 필터

@Override           
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(req) {
        //익명객체의 형태로 클래스를 하나 정의해보자. 
        @Override
        public String getParameter(String name) {
            if("who".equals(name)) {
                return "a001";
            }else {
                return super.getParameter(name);
            }
        }
    }; 
    log.info("{} 요청이 필터링됨.", req.getRequestURI());

    chain.doFilter(wrapper, response); //request -> wrapper 

    log.info("{} 에 대한 요청으로 생성된 응답이 필터링됨.", req.getRequestURI());
}

이제 진짜 필요한 필터를 만들어보자.

설계
1. 인코딩필터 : CEF
2. 멀티파트필터 : MF
파일관련처리하는 셋터가 리퀘스트에 없다.그래서 랩퍼가 필요하다 wrapper request. 

1. 초기화 파라미터로 인코딩을 설정해보자.

초기화 파람 설정.

  <filter>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<filter-class>kr.or.ddit.filter.mvc.CharacterEncodingFilter</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

 

흐어....ㅜㅜ

multipart....


1. 신원확인 - 인증

2. 권한 부여됐는지 확인 - 인가

보호자원에 대한 접근제

1. 무엇을 보호할 것인가? 보호자원에 대한 정의 ▶SecuredResources.properties

2. 

3. 자원에 설정된 권한에 맞춰 사람에게도 부여되는 권한

 

배열대상으로 이진탐색방법으로 검색을해야한다. 그러려면 정렬이 필요.


참고

base64인코딩

https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0_URI_%EC%8A%A4%ED%82%B4


OWASP

3년에 한번 또는 4년에 한번씩 그동안 가장 많았던 보안 공격, 취약점을 발표한다고 한다. 

https://www.appsealing.com/kr/2021%EB%85%84-owasp%EC%9D%98-10%EB%8C%80-%EC%B7%A8%EC%95%BD%EC%A0%90/

2021에 발표한 내용


request는 기본적으로 셋터가 없기 때문에 원본 리퀘스트를 수정하려면 adapter패턴 활용하여 wrapper를 생성한다.

자바시스템에서 표준화된 인증객체 principal

반응형