romworld

JSP 24 - 필터 (filter) 본문

WEB/JSP

JSP 24 - 필터 (filter)

inderrom 2023. 1. 16. 12:49

Request 필터

  • 인증(사용자 인증)
  • 요청 정보를 로그 파일로 작성
  • 암호화 인코딩 작업

Response 필터

  • 응답 결과 데이터 압축
  • 응답 결과에 내용 추가/수정
  • 총 서비스 시간 측정

Filter 인터페이스

  • init()  : 필터 인스턴스의 초기화 메서드
  • doFilter() : 필터 기능을 작성하는 메서드
  • destroy() : 필터 인스턴스의 종료 전에 호출되는 메서드

 

 

<AuthenFilter.java>

 

filter(javax.servlet.Filter) implements 받는다.

 

package filter;

import java.io.IOException;
import java.io.PrintWriter;

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

public class AuthenFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("Filter01 초기화..");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws IOException, ServletException {
		System.out.println("Filter01.jsp 수행 ...");
		// 요청 URI : Filter.jsp?name=새롬이
		String name = request.getParameter("name");
		
		if(name == null || name.equals("")) {
			// 톰캣에서 크롬으로 응답해주는 response객체의 인코딩을 UTF-8로 세팅
			// 한글을 보내기 위함
			response.setCharacterEncoding("UTF-8");
			response.setContentType("text/html; charset=UTF-8");
			
			PrintWriter writer = response.getWriter();
			String message = "입력된 name 값이 null입니다.";
			writer.println(message);
			return;
		}
		filterChain.doFilter(request, response);
	}


	@Override
	public void destroy() {
		System.out.println("Filter01해제...");
	}
}

 

 

<web.xml>

 

둘은 짝꿍! 같이 쓴다.

web.xml에서 mapping

  	<!--  java의 세계와 톰켓의 세계를 연결 -->
  	<!--  모든 요청/응답 사이에 AuthenFilter 동작 -->
  	<filter>
  		<filter-name>filter01</filter-name>	
  		<!--  src 패키지 다음 이름부터 -->
  		<filter-class>filter.AuthenFilter</filter-class>
  	</filter>
  	<filter-mapping>
  		<filter-name>filter01</filter-name>
  		<url-pattern>/ch12/filter01_process.jsp</url-pattern>
  	</filter-mapping>

 

 

<filter01.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>filter</title>
</head>
<body>
	<!--  /ch12/filter01_process.jsp?name=새롬이 -->
	<form action="/ch12/filter01_process.jsp">
		<p>이름 : <input type="text" name="name" /></p>
		<p><input type="submit" value="전송" /></p>
	</form>
</body>
</html>

 

<filter01_process.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>filter</title>
</head>
<body>
	<%	
		request.setCharacterEncoding("UTF-8");
		// /ch12/filter01_process.jsp?name=새롬이	
		String name = request.getParameter("name");  //새롬이
	%>
	<p>입력된 name 값 : <%=name%></p>
</body>
</html>


Filter (web.xml)에서 파라미터 가져오기

init을 활용해서 사용하지만 -> 잘 쓰지 않음 (이 방식을 이용하지 않음)

- filter는 인코딩을 하기 위한 사전공부 수준 ~

<web.xml>

	<!--  파라미터를 InitParamFilter 클래스의 init메소드로 던짐 -->
  	<!--  /ch12/filter-2_process.jsp이 요청되면 InitParamFilter 필터 수행 -->
  	<filter>
  		<filter-name>filter02</filter-name>	
  		<filter-class>filter.InitParamFilter</filter-class>
  		<!--  관리자 아이디/ 비밀 번호 셋팅 -->
  		<init-param>
  			<param-name>param1</param-name>
  			<param-value>admin</param-value>
  		</init-param>
  		<init-param>
  			<param-name>param2</param-name>
  			<param-value>1234</param-value>
  		</init-param>
  	</filter>
  	<filter-mapping>
  		<filter-name>filter02</filter-name>
  		<!--  * 넣으면 모두 -->
  		<url-pattern>/ch12/filter02_process.jsp</url-pattern>
  	</filter-mapping>

 

<IntiParamFilter.java>

package filter;

import java.io.IOException;
import java.io.PrintWriter;

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

public class InitParamFilter implements Filter {
	
	// 멤버변수
	private FilterConfig filterCongfig = null;
	
	//web.xml에서 파라미터로 넘어온 파라미터들을 filterConfig 매개변수로 받음
	// filterconfig : {"param1" : "admin", "param2" : "1234"}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("Filter02 초기화..");
		
		// 멤버변수로 할당
		this.filterCongfig = filterConfig;
	}
	// 크롬(내장객체.request, response) -> request(요청) -> 톰캣
	// 크롬							   <- response(응답) <- 톰캣
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("filter20 수행..");
		
		request.setCharacterEncoding("UTF-8");
		// filter02.jsp에서 filter02_process.jsp를 post방식으로 요청 시
		// <input type="text" name="id" />
		// <input type="text" name="passwd" />
		// filter02_process.jsp?id=admin&passwd=1234
		String id = request.getParameter("id");  // admin
		String passwd = request.getParameter("passwd");  // 1234
		
		// web.xml의 init-param 태그로 넘어온 파라미터와 비교해보자
		String param1 = filterCongfig.getInitParameter("param1");
		String param2 = filterCongfig.getInitParameter("param2");
		
		String message= "";
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter writer =response.getWriter();
		
		// 서로 비교해보자
		// param1과 param2 는 web.xml에서 넘어온 값들(DB)
		// id와 passwd는 request객체에 있던 값들(사용자 입력값들)
		if(id.equals(param1) && passwd.equals(param2)) { // 로그인 성공
			message = "로그인 성공했습니다.";
		}else {
			message = "로그인 실패했습니다.";
		}
		
		writer.println(message);
		// 필터가 여러개이면 다음 필터로 request/response객체를 전달해줌
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		System.out.println("Filter02 해제..");
	}

}

 

<filter02.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>Filter</title>
</head>
<body>
<!--  /ch12/filter02_process.jsp=id=admin&passwd=1234 -->
	<form action="/ch12/filter02_process.jsp" method="post">
		<p>아이디 : <input type="text" name="id" /></p>
		<p>비밀번호 : <input type="text" name="passwd" /></p>
		<p><input type="submit" value="전송" /></p>
	</form>
</body>
</html>

<filter02_process,jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>Filter</title>
</head>
<body>
	<% //스크립틀릿
		// filter02_process.jsp?id=admin&passwd=1234
		String id = request.getParameter("id");//admin
		String passwd = request.getParameter("passwd");//1234
	%>
	<c:set var="id" value="<%=id%>" />
	<c:set var="passwd" value="<%=passwd%>" />
	
	<script type="text/javascript">
		//jstl의 변수들을 J/S의 변수들로 받아보자
		let id = "${id}";
		let passwd = "${passwd}";
		//json
		let data = {"id":id,"passwd":passwd};
// 		let dataJson = JSON.parse(data);
		
		//JSON.stringify(dataJson)형태로 ajax 통신이 가능
		console.log("data : " + JSON.stringify(data));
	</script>
</body>
</html>

 


Filter를 이용해 Log 사용하기

<web.xml>

 

 

<LogFileFilter.java>

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

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

public class LogFileFilter implements Filter {
	
	//jsp에서 메시지를 보여야 하므로
	PrintWriter writer;
	
	//web.xml의 init-param에 {"filename" : "저장될경로"}를 넣어서
	// filterConfig 매개변수로 던짐
	/*
	 윈도우즈의 폴더 경로는 \\fh rnqns
	 <init-param>
	 	<param-name>filename</param-name>
	 	<param-value>c:\\logs\\gdi.log</param-value>
	  </init-param>
	 */
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// filename은 c:\\logs\\gdi.log
		String filename = filterConfig.getInitParameter("filename"); // 저장될 경로 및 파일명
		if(filename == null) throw new ServletException("로그 파일의 이름을 찾을 수 없습니다.");
		
		try {
			// new PrintWriter : 파일 객체 생성 (true : 기존 버퍼를 비움)
			// new FileWriter : 생성된 파일에 연동 (true : 누적됨(append))
			writer = new PrintWriter(new FileWriter(filename, true), true);
		}catch(IOException e) {
			throw new ServletException(); // web.xml과 관련된 것은 ServletException을 쓴다.
		}
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// s : 문자열  n : 다음줄로 이동
		writer.printf("현재일시 : %s %n", getCurrentTime());
		// 접속한 클라이언트 IP
		String clientAddr = request.getRemoteAddr();
		writer.printf("클라이언트 주소 : %s %n", clientAddr);
		
		// 다음 필터에 request, response 객체를 넘겨줌
		// 필터가 연속적으로 있다면 다음 필터로 제어 및 요청/응답 정보를 넘겨줌
		// 필터를 리소스에 적용
		chain.doFilter(request, response);
		
		// 문서의 콘텐츠 유형(MINE 타입)
		String contentType = response.getContentType();
		writer.printf("문서의 콘텐츠 유형 : %s %n", contentType);
		writer.println("-----------------------------------------");
	}
	
	// 필터를 종료하기 전에 호출
	@Override
	public void destroy() {
		// 객체를 메모리에서 제거
		writer.close();
	}
	
	// 현재 일시를 리턴해주는 메소드
	private String getCurrentTime() {
		// 출력 형식을 설정
		DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		// 날짜 객체 생성 (싱글톤 -주기억장치(ram)에 객체가 1회 생성. 전역변수처럼 공유되어 사용)
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(System.currentTimeMillis());
		// 현재 일시를 연/월/일 시:분:초 형식으로 바꿈(String타입)
		return formatter.format(calendar.getTime());
	}

}

 

 

c드라이브 -> logs 폴더 생성 -> gdi.log 파일 생성

 

 

<file02.jsp>를 실행시키면

log 문서에 log가 찍힌다.

 

Comments