■ 요청 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은 다음과 같다.
-. 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> |
출력화면① |
![](https://t1.daumcdn.net/cfile/tistory/177337475040275806)
|
출력화면② |
![](https://t1.daumcdn.net/cfile/tistory/1421E5495040277A01)
|