본문 바로가기

JSP/JSP Programming

[JSP] 요청 URI 자체를 명령어로 사용하는 방법

반응형

■ 요청 URI 자체를 명령어로 사용하는 방법

 -. 요청 파라미터를 명령어로 사용한느 방법은 간편하기는 하지만

     명령어가 파라미터로 전달되기 때문에 정보가 사용자에게 노출된다는 단점이 있다.

 -. 이런 문제를 방지하기위해서 요청 URI 자체를 명령어로 사용하는 방법이 있다.

 -. 요청 URI 자체를 명령어로 사용하는 방법은 요청되는 URI가 실제 페이지가 아니고 명령어 이므로

    악의적인 명령어로부터 사이트가 보호된다는 점과 요청되는 URL이 좀 더 자연스러워 진다는 점이다.

 -. 요청 URI자체를 명령어로 사용하는 컨트롤러 서블릿(CommandControllerURI)는 요청 파라미터를 명령어로 사용하는

    컨트롤러 서블릿(CommandController)의 proRequest() 메소드에서 String cmd = request.getParameter("cmd"); 를 대신하여

    다음과 같은 코드로 변경하면 된다.

 String cmd = request.getRequestURI();
        
        if(cmd.indexOf(request.getContextPath()) == 0) {
            
            cmd = cmd.substring(request.getContextPath().length());
        }

 -. 위 코드는 요청 URI에서 request.getContextPath() 부분만을 제거하여 cmd 변수에 저장한다.

 -. 웹 브라우저에 입력한 URL을 보면 다음과 같다.

 http://localhost:8181/ch21/ch21/list.do

 -. 여기서는 request.getRequestURI() 메소드에 의해서 얻어낸 요청 URI은 다음과 같다.

  /ch21/ch21/list.do

 -. request.getContextPath()는 웹 어플리케이션 부분인 "/ch21" 부분을 의미한다.

 -. request.getRequestURI() 메소드에 의해서 얻어낸 요청 URI에서 request.getContextPath() 부분을 제거하고 나면

    cmd 변수에 "/ch21/list.do"만 남는다.

 -. 설정 파일에 명령어와 명령어 처리 클래스를 매핑한 정볼르 저장할 때 다음과 같이 저장해야 한다.

  CommandURI.properties
 /ch21/list.do = ch21.controller.ListAction
 /ch21/write.do = ch21.controller.WriteAction


 -. CommandURI.properties 파일을 컨트롤러인 CommandControllerURI에서 읽어올 수 있도록 설정 파일의 정보를 web.xml 파일에 기록한다.

 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns="http://java.sun.com/xml/ns/javaee"

  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

<!--  요청 파라미터로 명령어를 전달하는 방법
  <servlet>
      <servlet-name>CommandController</servlet-name>
      <servlet-class>ch21.controller.CommandController</servlet-class>
      <init-param>
          <param-name>configFile</param-name>
          <param-value>C:\Workspace\ch21\WebContent\WEB-INF\Command.properties</param-value>
      </init-param>
  </servlet>
-->


<!--  요청 URI 자체를 명령어로 사용하는 방법 -->
  <!-- <servlet> 태그는 서블릿의 설정 정보를 처리할 수 있도록 한다. -->
  <servlet>
    <!-- <servlet-name> 태그에는 서블릿명을 기술한다. -->
    <!-- 이 태그를 사용하면 해당 서블릿이 ch21.controller.CommandControllerURI에 위치하더라도 -->
    <!-- http://localhost:8181/ch21/servlet/ch21.controller.CommandControllerURI 대신 -->
    <!-- http://localhost:8181/ch21/servlet/CommandControllerURI로 기술할 수 있다. -->
      <servlet-name>CommandControllerURI</servlet-name>
      <!-- <servlet-class> 태그에는 실제 서블릿 경로를 기술해 준다. -->
      <servlet-class>ch21.controller.CommandControllerURI</servlet-class>
      <!-- <init-param> 태그는 initial parameter를 설정한느 부분으로 -->
      <!-- 이 태그는 config.getInitParameter("configFile") 메소드를 통해 -->
      <!-- 파라미터의 이름을 읽어들여 파라미터의 값을 얻어낸다. -->
      <init-param>
          <!-- <param-name> 태그에는 config.getInitParameter 메소드의 전달인자로 -->
          <!-- 사용할 파라미터의 이름을 기술한다. -->
          <param-name>configFile</param-name>
          <!-- <param-value>는 설정 파일인 CommandURI.properties 파일의 경로명을 기술한다. -->
          <param-value>C:\Workspace\ch21\WebContent\WEB-INF\CommandURI.properties</param-value>
      </init-param>
  </servlet>
 
  <!-- <servlet-mapping> 태그는 <url-pattern> 태그의 값인 *.do와 같이 사용자의 요청이 오는 경우 -->
  <!-- <servlet-name> 태그의 값인 서블릿 CommandControllerURI가 그 요청을 받아서 처리해 주게 하는 것이다. -->
  <!-- 즉 사용자의 요청이 http://localhost:8181/ch21/ch21/list.do 와 같이 오게 되면 -->
  <!-- 이를 CommandControllerURI 서블릿이 처리하도록 환경 설정한다. -->
  <servlet-mapping>
      <servlet-name>CommandControllerURI</servlet-name>
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  ~~~~~~~~


</web-app>


 -. 요청 자체를 명령어로 사용하는 컨트롤러 서블릿 작성하기

  CommandControllerURI.java

package ch21.controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CommandControllerURI extends HttpServlet {
   
    // 명령어와 명령 처리 클래스를 쌍으로 저장할 해쉬 맵 객체 생성
    private Map commandMap = new HashMap();
   
    public void init(ServletConfig config) throws ServletException {
       
        // web.xml 파일의 configFile 태그의 초기화 파라미터(init-param)로 부터
        // 매핑정보를 저장하고 있는 설정 파일(CommandURI.properties)의 경로를 구한다.
        String configFile = config.getInitParameter("configFile");
       
        if(configFile == null) {
           
            configFile = "C:/Workspace/ch21/WebContent/WEB-INF/CommandURI.properties";
        }
       
        // 명령어와 이를 처리할 클래스의 매핑 정보를 저장할 Properties 객체 생성
        Properties prop = new Properties();
        FileInputStream fis = null;
       
        try {
           
            // 설정 파일(Command.properties)로 부터 파일 내용(매핑 정보)을 읽어온다.
            fis = new FileInputStream(configFile);
           
            // Command.properties 파일의 정보를 Properties 객체에 저장
            prop.load(fis);
        }
       
        catch(IOException e) {
           
            throw new ServletException(e);
        }
       
        finally {
           
            if(fis != null) {
               
                try {
                   
                    fis.close();
                }
               
                catch(IOException e) {
                   
                    e.printStackTrace();
                }
            }
        }
       
        // Properties 객체에서 키값들을 Set으로 얻어와서 iterator 메소드를 호출한다.
        Iterator keyIter = prop.keySet().iterator();
       
        // Iterator 객체로 다음 명령어가 있는지 판단해서 있다면 명령어를 얻어옴
        while(keyIter.hasNext()) {   
           
            String command = (String)keyIter.next();
           
            // 해당 명령어랑 매핑된 클래스 이름을 문자열 형태로 얻어옴
            String className = prop.getProperty(command);
           
            try {
               
                // 클래스의 이름이 문자열 형식이므로 이에 해당되는 클래스 생성
                Class handlerClass = Class.forName(className);
               
                // 해당 클래스로 객체 생성
                Object handlerInstance = handlerClass.newInstance();
               
                // <명령어, 핸들러 인스턴스>의 매핑정보를 해쉬맵에 저장한다.
                commandMap.put(command, handlerInstance);
            }
           
            catch(ClassNotFoundException e) {
               
                throw new ServletException(e);
            }
           
            catch(InstantiationException e) {
               
                throw new ServletException(e);
            }
           
            catch(IllegalAccessException e) {
               
                throw new ServletException(e);
            }
        }
    }
   
    // GET 방식으로 요청을 받음 : proRequest 메소드로 전달
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        proRequest(request, response);
    }
   
    // GET 방식으로 요청을 받음 : proRequest 메소드로 전달
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        proRequest(request, response);
    }
   
    protected void proRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        // Request 객체로부터 사용자의 요청을 파악하는 코드
        String cmd = request.getRequestURI();
       
        if(cmd.indexOf(request.getContextPath()) == 0) {
           
            cmd = cmd.substring(request.getContextPath().length());
        }
       
        // 사용자의 요청에 따른 알맞은 작업을 처리하는 코드
        String view = null;
        CommandAction com = null;
               
        try {
                   
            // 사용자의 요청인 명령어가 저장된 cmd 변수로 이에 해당되는 명령 처리
            com = (CommandAction) commandMap.get(cmd);
                   
            // 인스턴스의 레퍼런스 값을 얻어와서 해당 명령처리 클래스의 proRequest 메소드를 수행 후
            // 포워딩 할 JSP 페이지를 리턴값으로 얻어와 view에 저장한다.
            view = com.proRequest(request, response);
        }
               
        catch(Throwable e) {
                   
            throw new ServletException(e);
        }
               
        // RequestDispatcher를 사용하여 알맞은 뷰(JSP 페이지)로 포워딩
        RequestDispatcher dispatcher = request.getRequestDispatcher(view);
        dispatcher.forward(request, response);
    }
}

 list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 목록</title>
</head>
<body>
<%-- message 속성의 값을 msg 변수에 저장한다.--%>
<c:set var = "msg" value = "${message}" />

<%-- msg 변수의 내용을 화면에 출력한다. --%>
<c:out value = "${msg}" />
</body>
</html>
 write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 목록</title>
</head>
<body>
<%-- message 속성의 값을 msg 변수에 저장한다.--%>
<c:set var = "msg" value = "${message}" />

<%-- msg 변수의 내용을 화면에 출력한다. --%>
<c:out value = "${msg}" />
</body>
</html>

 출력화면

 출력화면





반응형