본문 바로가기
JSP

221207 Filter

필터란 FrontController(서블릿)으로 들어가기 전 요청을 가로채 검사하는 역할을 하는 것

 

로그인한 사람만 글을 읽거나 수정할 수 있도록 컨트롤러 if문 or switch case문 안에 

if(command.equals("/board/board_write.board")){ //등록화면

      if(session.getAttribute("user_id")==null){

             response.sendRedirect("../user/user_login.user");

             return; //리다이렉트나 forward는 한번만 발생해야 하기 때문에 return으로 중지

       }

request.getRequestDispatcher("board_write.jsp").forward(request, response);

}

로 할 수도 있다.

 

그런데 이 방식은 컨트롤러 내용이 많을수록 지저분해짐

=>필터 사용!

클라이언트->'필터'->컨트롤러->서비스 or 화면ui

 

필터 클래스는 일반 자바 파일로 생성함(Filter파일이 있다)

생성 후 Filter인터페이스를 상속받음

일반적으로, doFilter메서드를 오버라이딩한다.

 

사용 후 chain.doFilter(request, response); 메서드를 반드시 사용한다.

이 메서드는 연결된 필터가 있으면 다음 필터로, 없으면 컨트롤러로 이동한다

chain객체-필터를 다른 필터로 연결

 

 

필터도 어노테이션이 있다.

필터가 어디서 동작할 건지 경로를 지정해야 함.

1. 어노테이션을 이요하여 배열{ }안에 동작할 요청을 넣거나,

@WebFilter({"/board/board_write.board",
"/board/board_modify.board", 
"/board/registFrom.board",
"/board/updateFrom.board",
"/board/board_delete.board"})

2. Web.xml에 filter를 등록할 수도 있음.

서블렛을 Web.xml에 등록했던 것과 같다. 필터 선언하고, 필터 매핑

 

<filter>
   <filter-name>필터 이름</filter-name>
   <filter-class>생성한 필터 경로

</filter>
  
<filter-mapping>
<filter-name>필터 이름</filter-name>
<url-pattern>필터를 사용할 경로</url-pattern>

</filter-mapping>  

필터를 2개, 3개 등 여러개 걸쳐 나갈 때는 반드시 두번째 방법을 쓴다.

 

+)

init-필터가 시작할 때 사용할 기능

destroy-필터가 없어질 때 사용할 기능

 

AuthFilter

package com.example.util.filter;

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

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

//필터를 실행할 요청 경로
@WebFilter({"/board/board_write.board",
			"/board/board_modify.board", 
			"/board/registFrom.board",
			"/board/updateFrom.board",
			"/board/board_delete.board"})
public class AuthFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		
		request.setCharacterEncoding("utf-8");
		
		//권한검사
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		
		//req에서 세션을 얻음
		HttpSession session = req.getSession();
		String user_id =(String)session.getAttribute("user_id");
		
		//user_id==null이라면 권한이 없다는 의미
		if(user_id == null) {
			
			String path = req.getContextPath();//컨텍스트패스
			
			
			res.setContentType("text/html; charset=utf-8");
			PrintWriter out = res.getWriter();
			out.println("<script>");
			out.println("alert('권한이 필요한 기능입니다');");
			out.println("location.href='"+ path +"/user/user_login.user" +"';");
			out.println("</script>");
			
			return;//함수를 종료하면 컨트롤러로 연결되지 않음
		}
		
		
		chain.doFilter(request, response);//필터가 여러개라면 다음 필터로 연결. 꼭 써줘야 함. 다음 필터가 없으면 원래 요청이 들어오는 컨트롤러로 연결
	}

}

HttpServletRequest는 ServletRequest의 자식

따라서 사용하기 위해서는 형변환이 필요

response도 마찬가지.

 

chain.doFilter를 만나기 전에 리다이렉트가 있으면 return을 넣어서 한번 끊어줘야 한다.

 

 

필터를 사용하여 user_id==null(로그인을 안한 상태)이면 수정, 업데이트, 삭제, 글쓰기에 접근할 수 없도록 만듦

메시지 출력문을 넣었기 때문에 아이디가 없을 때 사용하면 메시지가 뜨고 login페이지로 이동한다.

 

 

 

AuthFilter2

package com.example.util.filter;

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

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebFilter({"/board/board_modify.board",
			"/board/updateForm.board",
			"/board/board_delete.board"})//경로 수정화면, 수정기능, 삭제기능 
public class AuthFilter2 implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
		
		/*
		 * 세션의 user_id와 request로 넘어오는 작성자가 다르면 수정불가.
		 * 
		 * 1.각 요청경로에서 writer가 파라미터로 반드시 전달되도록 처리.
		 * 
		 */
		request.setCharacterEncoding("utf-8");
		
		//권한검사
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		
		//각 요청에 넘어오는 writer 파라미터
		String writer = req.getParameter("writer");
		
		//세션에 저장된 user_id
		HttpSession session=req.getSession();
		String user_id =(String)session.getAttribute("user_id");
		
		
		//System.out.println("작성자"+writer);
		//System.out.println("세션아이디"+user_id);
		
		//세션이 없거나 or 작성자와 세션이 다른 경우
		if(user_id==null||!writer.equals(user_id)) {
			String path = req.getContextPath();//컨텍스트패스
			
			
			res.setContentType("text/html; charset=utf-8");
			PrintWriter out = res.getWriter();
			out.println("<script>");
			out.println("alert('권한이 필요한 기능입니다');");
			out.println("location.href='"+ path +"/board/board_list.board" +"';");
			out.println("</script>");
			return;
			
		}
		
		
		chain.doFilter(request, response);
	}

}

필터를 사용하여 user_id==null(로그인을 안한 상태)이거나 writer와 user_id가 다를 경우 

수정, 업데이트, 삭제에 접근할 수 없도록 만듦

메시지 출력문을 넣었기 때문에 아이디가 없을 때 사용하면 메시지가 뜨고 list로 이동한다.

 

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
  <display-name>JSPWeb</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  
  
  <!-- 필터 등록하는 방법과 필터체이닝 -->
  <filter>
  	<filter-name>A</filter-name>
  	<filter-class>com.example.util.filter.AuthFilter</filter-class>
  </filter>
  
<filter-mapping>
	<filter-name>A</filter-name>
	<url-pattern>/board/board_write.board</url-pattern>
</filter-mapping>  

  <filter>
  	<filter-name>B</filter-name>
  	<filter-class>com.example.util.filter.AuthFilter2</filter-class>
  </filter>
  
<filter-mapping>
	<filter-name>B</filter-name>
	<url-pattern>/board/board_write.board</url-pattern>
</filter-mapping>  

  
</web-app>

 

 

board_write

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@include file="../include/header.jsp" %>

<div align="center" class="div_center">
	<h3>게시판 글 작성 페이지</h3>
	<hr>
	
	<form action="registForm.board" method="post">
		<table border="1" width="500">
			<tr>
				<td>작성자</td>
				<td>
					<input type="text" name="writer" value="${sessionScope.user_id }" size="10" readonly required>
				</td>
			</tr>
			<tr>
				<td>글 제목</td>
				<td>
					<input type="text" name="title" required>
				</td>
			</tr>
			<tr>
				<td>글 내용</td>
				<td>
					<textarea rows="10" style="width: 95%;" name="content"></textarea>
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<input type="submit" value="작성 완료">
					&nbsp;&nbsp;
					<input type="button" value="목록" onclick="location.href='board_list.board'">         
				</td>
			</tr>
			
		</table>
	</form>
	
</div>

<%@include file="../include/footer.jsp" %>

필터를 통해 아이디를 받아서 writer에 value로 넣음

 

 

board_content

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

<%@include file="../include/header.jsp" %>

<div align="center" class="div_center">

	<h3>게시글 내용 보기</h3>
	<hr>
	<table border="1" width="600">
		<tr>
			<td width="20%">글번호</td>
			<td width="30%">${vo.bno }</td>
			
			<td width="20%">조회수</td>
			<td width="30%">${vo.hit }</td>
		</tr>
		<tr>
			<td>작성자</td>
			<td>${vo.writer }</td>
			
			<td>작성일</td>
			<td ><fmt:formatDate value="${vo.regdate }" pattern="yyyy-MM-dd HH시 mm분 ss초"/></td>
		</tr>
		
		<tr>
			<td width="20%">글제목</td>
			<td colspan="3">${vo.title }</td>
		</tr>
		<tr>
			<td width="20%">글내용</td>
			<td colspan="3" height="120px">${vo.content }</td>
		</tr>
		
		<tr>
			<td colspan="4" align="center">
				<input type="button" value="목록" onclick="location.href='board_list.board'">&nbsp;&nbsp;
				<c:if test="${sessionScope.user_id != null }">
				<input type="button" value="수정" onclick="location.href='board_modify.board?bno=${vo.bno}&writer=${vo.writer }' ">&nbsp;&nbsp;
				<input type="button" value="삭제" onclick="location.href='board_delete.board?bno=${vo.bno}&writer=${vo.writer }'">&nbsp;&nbsp;
				</c:if>
			</td>
		</tr>
	</table>
	
	
	

	

</div>

<%@include file="../include/footer.jsp" %>

<c:if test="${sessionScope.user_id !=null}">를 통해 조건을 줌

로그인을 하지 않아서 user_id값이 없으면 수정과 삭제 버튼이 아예 보이지 않는다.