다연이네

[days09] 필터(Filter) 본문

JSP

[days09] 필터(Filter)

 다연  2021. 1. 6. 13:38
반응형

1.  필터(Filter)
     ㄱ.  필터 정의 ? http 요청 -> 변경을 할 수 있는 재사용 가능 클래스
                          http 응답 -> 변경    "    (예.  응답시 암호화 필요하면 암호화할수 있는 필터 거침)
                                     데이터      암호화 (필터)
                                   /board/ 안의 모든 것(*)들 응답할때 무조건 암호화 필터 거치라하면 일일히 하지 않아도 됨
                                   요청할때                     
                                -게시판 글쓰기 작업   인증/권한 필터 -> 없으면 로그인 페이지 이동
                                -게시판 글수정          인증/권한 필터
                                -게시판 글삭제          인증/권한 필터
                        하나의 필터만 만들어두면 요청url패턴에 그 필터만 걸어두면 항상 요청 들어오면 그 필터를 거칠 것

     ㄴ.  필터 체인 (chain) - 여러개의 필터가 모여 하나의 필터 체인을 형성한다. 
         [클]  -> 요청 -> [로그인 필터] -> [다른 필터(예. 파라미터 체크 필터)] -> [다른 필터] -> . . .  -> JSP/Servlet
                                   로그인페이지로 이동
           필터들이 차례로 연결되어 순차적으로 밟아나가는 것
         [클] <-응답 <- [암호화 필터] <- [XML변환필터](html/text->XML) <- html  JSP/Servlet
     
          필터는 값 변환, 체크 뿐만 아니라 요청을 이동시키는 역할도 한다.  (로그인 페이지로 이동 등 )

     ㄷ.  필터를 구현: 3가지 핵심 클래스/인터페이스
         1) javax. servlet. Filter 인터페이스: 필터를 만드려면 Filter 인터페이스를 구현(implement)
         2) javax. servlet. ServletRequestWrapper 클래스: 필터가 요청을 변경한 결과를 저장하는 래퍼클래스
         3) javax. servlet. ServletResponseWrapper 클래스: 필터가 응답을 변경하기 위해 사용하는 래퍼클래스
         
    ㄹ.  필터 클래스를 컴파일하려면 lib\servlet-api. jar 파일이 클래스 패스에 추가
         이클립스로 개발할 때는 필요 없다 
         
    ㅁ.  Filter 인터페이스
        1) init(): 필터 초기화 호출되는 메소드
        2) destroy(): 웹 컨테이너에서 제거될 떄 호출되는 메소드
        3) ***doFilter(): 필터 기능을 구현하는 메소드
                                    chain을 이용해서 다음 필터로 이동(전달)
                                    -> request 파라미터 이용해서 [요청]의 필터 작업 수행
                                    
                   기준                 (chain. doFilter()메소드를 호출하면 다음 필터로 전달)
                   
                                    -> response 이용해서 [응답]의 필터 작업 수행
        4) doFilter(request, response, FilterChain chain)
            FilterChain chain 세번쨰 매개변수를 통해서 다음 체인으로 요청/응답을 전달할 수 있다. 


    ㅂ.  필터도 서블릿처럼 web. xml 등록
        1) web. xml
        2) WebFilter 어노테이션


    ㅅ.  예제 필터 작성
        ***1) 요청할 때 파라미터가 존재하지 않는 경우 파라미터의 값을 ""로 처리하는 요청 래퍼 클래스 작성
               com. filter. NullParameterRequestWrapper (나중에)
         2) 인증 필터
               ㄱ) com. filter. LoginCheckFilter 클래스 생성
               ㄴ) web. xml 필터 등록
               ㄷ) days09/board/ex01_list. jsp
                 days09/member/ex01_loginForm. jsp 
                 
                 ex01. jsp ->
                 글목록 클릭 -> 로그인 체크필터 -인증O->글목록 ex01_list. jsp
                                                    -인증X->로그인페이지 ex01_loginForm. jsp
                                                    id/passwd     -> session. setAtrribute("member",id)저장 후 ->ex01. jsp?ok 
                                                                                                                                                            (근데 로그인 하면 바로 목록페이지로 이동해야 한다) 
          
    ㅇ.  필터 응용
         1) 인증/권한
         2) 캐싱 필터 (임시기억공간)
         3) 자원 접근에 대한 로깅
         4) 응답 데이터 변환(암호화, html->xml 변환, 응답 헤드 변환 등등)
         5) 공통 기능 실행. . (인증 기능 포함)

 

 

 

 

 

 

게시판을 만들 때, 게시판 목록에 접근하려면 로그인이 필요한 경우가 있다.

로그인을 하지 않고 게시판 목록을 클릭하면 -> 로그인 화면으로 이동하게 필터 처리를 해보자

(* 로그인을 하고 게시판 목록을 클릭하면 바로 목록이 보여진다)

(* 로그인 버튼을 클릭하면 바로 목록으로 이동한다)

 

2. 로그인하지 않은 경우 로그인 페이지로 이동
3. 로그인 완료시 목록으로 이동 (로그아웃 버튼 클릭하면->)
4. 메인 페이지로 이동

*로그인을 먼저 한 상태에서 게시판 글 목록을 클릭하면 바로 목록으로 이동한다.

 

ex01.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
   });
</script>
</head>
<body>
 
 
 <a href="/jspPro/days09/board/ex01_list.jsp">게시판 글 목록</a><br>
 <a href="/jspPro/days09/board/ex01_edit.jsp">게시판 글 수정</a><br>
 
<!--  
메인페이지에서 로그인 버튼을 클릭할 때는 당연히 로그인 후에 메인페이지로 이동하면 됨
글 목록이나 수정을 누르려했는데 로그인 페이지로 이동하면 로그인 후에 해당 페이지(목록이나 수정)로 가야한다.
=>ex01_loginForm 가서
 --> 
 <a href="/jspPro/days09/member/ex01_loginForm.jsp">로그인</a><br>
 
 
 
 <a href="/jspPro/days09/xml/booklist.xml">booklist.xml</a>
 

</body>
</html>

ex01_list.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
   });
</script>
</head>
<body>
리스트 
로그인 아이디 : ${mem }<br>
<a href="<%=request.getContextPath()%>/re01/mem/logout.jsp">로그아웃</a>
</body>
</html>

 

필터 (web.xml 등록 필수)

LoginCheckFilter.java

package com.filter;

import java.io.IOException;

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

public class LoginCheckFilter  implements Filter{

	@Override
	public void destroy() {
		
		
	}//destroy

	
	//글 목록 요청
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("> LoginCheckFilter.doFilter() ...");
		//인증O (member 세션!=null) => 다음 체인 필터(요청URL) 이동
		//인증 X => member/ex01_loginForm.jsp 이동
		//세션 안에 member라는 이름으로 값이 들어가있냐(==로그인했냐) 안들어가있냐 체크
		
		//매개변수에 Http가 안붙어 있으니 다운캐스팅 필요 (ServletRequest가 부모)
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		HttpSession session = httpRequest.getSession(false); //true/false 구별 필수
		//false : 세션이 없을때 null반환
		
		//System.out.println("원래 요청 "+httpRequest.getRequestURI()); //원래 가고자 했던 경로
		///jspPro/days09/board/ex01_list.jsp
		//요청한 url을 어딘가에만 저장 한다면 다른 페이지 ok 할때 얘를 location으로 잡으면 될 것이다.
		//p/r/s/a 스코프에 어딘가 저장 필요, 또는 쿠키에 저장 == 상태관리 하자는 의미
		//강사님 선택 : 세션 (쿠키도 가능, page,request은 의미없음)
		//그러나 지금은 포워딩으로 이동하기 때문에 request객체는 전달되어지므로 저장 필요 없음
		//원래는 포워딩되어지면 안된다 (요청 url이 로그인 폼인데 ex01_list.jsp로 뜨기 때문에)
		//로그인폼 가서 hidden
		//세션에 저장하는 것도 하나의 방법이다 어떤 식으로든 상태관리해서 페이지에서 알 수 있어야 함
		//session.setAttribute("referer", httpRequest.getRequestURI());
		//.ok가서 session.getAttribute("referer");
		
		boolean loginFlag = false;
		//인증받았다면 true
		
		if (session!=null) {
			if(session.getAttribute("member")!=null) {
				loginFlag = true;
			}
		}//if
		
		if (loginFlag) {
			chain.doFilter(request, response);
			//다음 연결된 체인이나 원래 요청으로 이동하라
		} else {
			//로그인 안했으면 로그인 페이지로
			String path = "/days09/member/ex01_loginForm.jsp";
			RequestDispatcher dispatcher = request.getRequestDispatcher(path);
			dispatcher.forward(request, response);
			}
		
	}//doFilter

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
		
	}//init

}//class

web.xml

  <filter>
  <filter-name>LoginCheck</filter-name>
  <filter-class>com.filter.LoginCheckFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>LoginCheck</filter-name>
  <url-pattern>/days09/board/*</url-pattern>
  </filter-mapping>

로그인 폼

/days09/member/ex01_loginForm.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<% //참고인
 String referer = request.getHeader("Referer");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
   });
</script>
</head>
<body>
<h3>ex01_loginForm.jsp</h3>

<form action="<%=request.getContextPath() %>/days09/member/ex01_loginForm_ok.jsp">
   아이디: <input type="text" name="id" /><br>
   비밀번호: <input type="password" name="passwd" /><br>
   <input type="submit" value="로그인" />
   
   <%-- <input type="hidden" name="referer" value="<%=referer %>" /> --%>
   <!-- hidden태그에 담아서 넘겨주려했는데 안하려고 주석처리 -->
</form>

</body>
</html>

로그인 폼에서 넘어가는 폼 (로그인 성공 폼)

/days09/member/ex01_loginForm_ok.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
//String referer = session.getAttribute("referer");
//session.removeAttribute("referer"); //시용한 후 지우기
%>

<% //참고인 추가
 String referer = request.getHeader("Referer");

//System.out.println(">referer:"+referer); //이전 페이지를 나타냄(어디서 왔는지)
//http://localhost/jspPro/days09/board/ex01_list.jsp (포워딩때문에 이 경로 잡힘)
//http://localhost/jspPro/days09/board/ex01_edit.jsp (포워딩때문에 이 경로 잡힘)

%>


<%
 String id = request.getParameter("id");
 // 바로 인증 처리 (가정) (실패하면 다시 로그인 페이지로 이동해야함)
session.setAttribute("member", id);
 
 //무조건 ex01.jsp(메인페이지로) 이동하는 것이 아니라
 //[어떤 URL 요청]에 의해 인증(로그인)이 필요해 이 페이지에 왔는지 보고 그 페이지로 보내야 한다.
 

 //필터에 가서 
 String location = "/jspPro/days09/ex01.jsp?ok"; //얘는 필터 안거침 /days09/board/*가 아니라서
 
 if(referer.indexOf("ex01_loginForm.jsp")==-1){ // == 필터 거쳐서 왔다면
	 location = referer;
 }
 
 response.sendRedirect(location);
 
%>

로그아웃 폼 (세션 삭제)

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
    session.invalidate();
   String location = "/jspPro/days09/ex01.jsp";
   response.sendRedirect(location);
%>

 

반응형
Comments