본문 바로가기
JSP 웹프로그래밍

JSP #3 : 페이지 이동 & 정보 공유 (230103)1

by haheehee 2023. 1. 3.

페이지이동

 

++ 데이터를 포함하지 않는 경우 ++

- 사용자 요청을 처리한 후, 별도의 데이터를 포함하지 않는다면, 해당 페이지로 바로 리디렉션

- (데이터 저장이 세션에 되었다면, 세션 정보는 세션이 유효한 동안 모든 페이지에서 참조 가능하므로, 리디렉션에서도 데이터 참조 가능)

- JSP와 Servlet(서블릿) : response.sendRedirect()

response.sendRedirect("main.jsp");

 

++ 데이터를 포함하는 경우 ++

- request 속성으로 데이터를 넣고, 원하는 페이지로 포워딩(forwarding)해야 한다.

- 데이터의 목적에 따라 세션(session)이나 application 사용

- 여러 데이터 포함 가능

// JSP로 구현
<%
    request.setAttribute("member", m);
    pageContext.forward("user.jsp");
%>
// 서블릿으로 구현 *********짱중요**********
doGet(...) {
    ...
    request.setAttribute("member", m);
    RequestDispatcher dispatcher = request.getRequestDispatcher("user.jsp");
    dispatcher.forward(request, response);
}
// 스프링 프레임워크로 구현
@GetMapping("info")
public String getMemberInfo(int id, Model model) {
    ...
    model.addAttribute("member", m);
    return "user";
}

 


++ 포워드 ++

- 하나의 서블릿에서 다른 서블릿이나 JSP와 연동하는 방법

  • 요청(request)에 대한 추가 작업을 다른 서블릿에게 수행하도록 한다.
  • request에 포함된 정보를 다른 서블릿이나 JSP와 공유한다.
  • request에 정보를 포함시켜 다른 서블릿에 전달할 수 있다.
  • 모델2 개발 시 서블릿에서 JSP로 데이터를 전달하는 데 사용된다.

1. redirect

- HttpServletResponse 객체의 sendRedirect() 메서드를 이용

- 웹 브라우저에 재요청하는 방식

sendRedirect("포워드할 서블릿 또는 JSP");

- 서블릿의 요청이 클라이언트의 웹 브라우저를 다시 거쳐 요청되는 방식

출처 :&nbsp;https://hleee.medium.com/%EC%84%9C%EB%B8%94%EB%A6%BF%EC%9D%98-%ED%8F%AC%EC%9B%8C%EB%93%9C-%EB%B0%A9%EB%B2%95-3e362ffcbcea

-       1. 클라이언트의 웹 브라우저에서 첫번째 서블릿에 요청

        2.첫번째 서블릿은 sendRedirect()메서드 사용해 두 번째 서블릿을 웹 브라우저를 통해 요청

        3. 웹 브라우저는 sendRedirect()메서드가 지정한 두 번째 서블릿 다시 요청

- (sendRedirect()는 값전달 안됨!!)

 

redirect 실습.

// 첫번째 서블릿 
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		response.sendRedirect("second");
	}
}

// 두 번째 서블릿 
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		out.println("sendRedirect를 이용한 redirect 실습");
		out.println("</body></html>");
	}
}

첫번째 서블릿으로 서버로 실행하면

최종적으로 웹 브라우저에 표시되는 매핑 이름은 /second이다. 

/first로 요청하면 sendRedirect()를 호출하여 웹 브라우저에게 다시 /second를 요청하는 것.

 


2. Refresh

- HttpServletResponse 객체의 addHeader() 메서드를 이용

- 웹 브라우저에 재요청하는 방식 (사진참고)

response.addHeader("Refresh",경과시간(초);url=요청할서블릿orJSP");

출처 :&nbsp;https://hleee.medium.com/%EC%84%9C%EB%B8%94%EB%A6%BF%EC%9D%98-%ED%8F%AC%EC%9B%8C%EB%93%9C-%EB%B0%A9%EB%B2%95-3e362ffcbcea

-      1. 클라이언트의 웹 브라우저에서 첫번째 서블릿에 요청

        2.첫번째 서블릿은 addHeader()메서드 사용해 두 번째 서블릿을 웹 브라우저를 통해 요청

        3. 웹 브라우저는 addHeader()메서드가 지정한 두 번째 서블릿 다시 요청

- delay 딜레이가 필요한 경우 이것을 사용!!

 

refresh 실습

// 첫번째 서블릿
@WebServlet("/first_2")
public class FirstServlet_2 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		response.addHeader("Refresh","1;url=second_2"); // 1초 후 서블릿 second로 재요청
	}
}

// 두 번째 서블릿
@WebServlet("/second_2")
public class SecondServlet_2 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		out.println("refresh를 이용한 redirect 실습");
		out.println("</body></html>");
	}
}

 

브라우저에서 /first로 요청하면

1초 후, /second로 재요청된다.

 

 


 redirect 방법으로 최초 요청한 서블릿에서

GET 방식으로 다른 서블릿으로 데이터를 전달 실습

// 첫번째 서블릿
@WebServlet("/first_4")
public class FirstServlet_4 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		response.sendRedirect("second_4?name=lee");
	}
}

// 두번째 서블릿
@WebServlet("/second_4")
public class SecondServlet_4 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String name=request.getParameter("name");
		
		out.println("<html><body>");
		out.println("이름 : " + name);
		out.println("<br>");
		out.println("</body></html>");
	}
}

 

GET방식을 이용해 redirect되는 서블릿 /second로 이름이 전달된다.

 

 


 

3. location

- 자바스크립트 location 객체의 href 속성을 이용 (주소창)

- 자바스크립트에서 재요청하는 방식

location.href='요청할서블릿orJSP';

 

location 실습

// 첫 번째 서블릿
@WebServlet("/first_3")
public class FirstServlet_3 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		response.addHeader("Refresh","1;url=second_2"); // 1초 후 서블릿 second로 재요청
		
		out.print("<script type='text/javascript'>");
		out.print("location.href='second_3';");
		out.println("</script>");
	}
}

// 두 번째 서블릿 
@WebServlet("/second_3")
public class SecondServlet_3 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		out.println("location을 이용한 redirect 실습");
		out.println("</body></html>");
	}
}

 

 


4. dispatch

- 일반적으로 포워딩 기능이 dispatch이다.

- 서블릿이 직접 요청하는 방법

- RequestDispatcher 클래스의 forward() 메서드 사용

- 가장 많이 사용

- back쪽에서 처리 (1~3은 프론트에서 처리)

RequestDispatcher dis = request.getRequestDispatcher("포워드할서블릿orJSP");
dis.forward(request, response);

- dispatch 방식은 클라이언트의 브라우저를 거치지 않고 서버에서 포워딩이 진행

-     1. 클라이언트의 웹 브라우저에서 첫 번째 서블릿에 요청

      2. 첫 번째 서블릿은 RequestDispatcher를 이용해 두 번째 서블릿으로 포워드

 

dispatch 실습

// 첫번째 서블릿
@WebServlet("/first_5")
public class FirstServlet_5 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		
		RequestDispatcher dispatch = request.getRequestDispatcher("second_5");
		dispatch.forward(request,  response);
	}
}

// 두번째 서블릿
@WebServlet("/second_5")
public class SecondServlet_5 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		out.println("<html><body>");
		out.println("dispatch를 이용한 forward 실습");
		out.println("</body></html>");
	}
}

웹 브라우저 주소 창의 URL이 변경되지 않고 그대로이다. (first_5로)

-> 서블릿의 포워드가 서버에서 실행되었기 때문!!!!!!!

 

 

dispatch 실습2

// 첫번째 서블릿
@WebServlet("/first_6")
public class FirstServlet_6 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		
		PrintWriter out = response.getWriter();
		RequestDispatcher dispatch = request.getRequestDispatcher("second_6?name=lee");
		dispatch.forward(request,  response);
	}
}

// 두번째 서블릿
@WebServlet("/second_6")
public class SecondServlet_6 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String name = request.getParameter("name");
		
		out.println("<html><body>");
		out.println("이름 : " + name);
		out.println("<br>");
		out.println("dispatch를 이용한 forward 실습");
		out.println("</body></html>");
	}
}

GET방식으로 dispatch를 이용해 데이터를 전달 -> URL 변경되지 않음.

 


++ 바인딩 ++

- 웹 프로그램을 실행할 때, 데이터를 서블릿 관련 객체에 저장하는 방법

- HttpServletRequest, HttpSession, ServletContext 객체에서 사용

- 저장된 데이터는 프로그램 실행 시 서블릿이나 JSP에서 공유해서 사용

  • setAttribute(String name, Object obj) : 데이터를 각 객체에 바인딩
  • getAttribute(String name) : 각 객체에 바인딩된 데이터를 name으로 가져옴
  • removeAttribute(String name) : 각 객체에 바인딩된 데이터를 name으로 제거

HttpServletRequest를 이용한 redirect 포워딩 시 바인딩 실습

// 첫번째 서블릿
@WebServlet("/first_4_1")
public class FirstServlet_4_1 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		
		request.setAttribute("address", "대전시 서구");
		response.sendRedirect("second_4_1");
	}
}
//두번째 서블릿
@WebServlet("/second_4_1")
public class SecondServlet_4_1 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String address = (String)request.getAttribute("address");
		
		out.println("<html><body>");
		out.println("주소 : " + address);
		out.println("<br>");
		out.println("redirect를 이용한 바인딩 실습");
		out.println("</body></html>");
	}
}

null이 출력되는 이유 : 

브라우저에서 요청할 때 서블릿이 전달되는 첫번째 request는 웹 브라우저를 통해 재요청되는 두번째 request와 다르다.

redirect방식으로는 서블릿에서 바인딩한 데이터를 다른 서블릿으로 전송 불가능

 


HttpServletRequest를 이용한 dispatch 포워딩 시 바인딩

// 1 서블릿
@WebServlet("/first_4_2")
public class FirstServlet_4_2 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		
		request.setAttribute("address", "대전시 서구");
		RequestDispatcher dispatch = request.getRequestDispatcher("second_4_2");
		dispatch.forward(request, response);
	}
}
//2 서블릿
@WebServlet("/second_4_2")
public class SecondServlet_4_2 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String address = (String)request.getAttribute("address");
		
		out.println("<html><body>");
		out.println("주소 : " + address);
		out.println("<br>");
		out.println("dispatch를 이용한 바인딩 실습");
		out.println("</body></html>");
	}
}

첫 번째 서블릿에서 두번째로 전달되는 request가 브라우저를 거치지 않고 바로 전달

-> 첫번째의 request에 바인딩된 데이터가 그대로 전달된 것이다.

 

 


++ URL rewriting ++

- HTTP의 Query String을 이용하는 방식

- URL에 파라미터를 추가해 서버로 요청 하는 형식

- 정보 유지를 위해 파라미터를 매 페이지마다 확인, 계속 추가 해야함.

- 복잡한 정보 유지는 어려움


++ 쿠키(Cookie) ++

- 클라이언트(PC)에 저장되는 작은 정보 (웹 페이지들 사이의 공유 정보를)

- 서버의 요청에 의해 브라우저가 저장, 서버가 요청할 때 제공

 

- 한페이지에 한 쿠키 (도메인당 쿠키가 만들어진다. -웹 사이트당 하나의 쿠키)

 

- 파일로 클라이언트의 컴퓨터에 저장되는 방식

- 보안상 문제

- 광고 혹은 기타 목적으로 사용자 추적에 이용될 수 있음

- 이러한 목적이라면 사용자 정보 활용 동의가 필요 (클라이언트 브라우저에서 사용 유무를 설정할 수 있음)

- 재방문 확인 용도로 많이 사용

- ‘name=value’ 형식 사용 (유효 기간, 요청 경로, 도메인 지정 등의 부가 속성)

- 주로 자바스크립트를 통해 처리 (HttpOnly 설정으로 서버에서만 사용할 수 있음)

- 저장 정보 용량에 제한(파일 용량 : 4kb)

- 1. 쿠키 생성(서버), 2. 쿠키 전송(서버-브라우저), 3. 쿠키 저장(브라우저), 4. 재방문 시 쿠키 전달(브라우저-서버)

response.addCookie(new Cookie("name", "hahee"));
response.addCookie(new Cookie("phone", "010-1111-1111"));

쿠키 파일

- 쿠키 실행

  1. 브라우저로 사이트에 접속
  2. 서버는 정보를 저장한 쿠키 생성
  3. 생성된 쿠키를 브라우저로 전송
  4. 브라우저 : 서버로 받은 쿠키 정보 쿠키 파일에 저장
  5. 브라우저 : 다시 접속해 서버가 쿠키 전송 요청하면 부라우저는 쿠키 정보를 서버에 줌
  6. 서버는 쿠키 정보 사용해 작업

- 쿠키 API

  • javax.servlet.http.Cookie
  • HttpServletResponse의 addCookie() 메서드 - 클라이언트 브라우저에 쿠키를 전송하고, 저장
  • HttpServletRequest의 getCookie() 메서드 - 쿠키를 서버로
속성 Persistence 쿠키 Session 쿠키
생성위치 파일로 생성 브라우저 메모리에 생성
종료시기 쿠키 삭제, 쿠키 설정값이 종료되면 브라우저를 종료하면
최초 접속 시 전송여부 서버로 전송 최초 접속시 전송되지 않음
용도 로그인 유무 혹은 팝업창 제한 사이트 접속 시 Session인증 정보 유지
Method Description
getComment() 쿠키에 대한 설명
getDomain() 쿠키의 유효한 도메인 정보
getMaxAge() 쿠키 유효 기간
getName() 쿠키 이름
getPath() 쿠키의 디렉토리 정보
getValue() 쿠키의 설정 값
setComment(String) 쿠키에 대한 설명
setDomain(String) 쿠키의 유효한 도메인을 설정
SetMaxAge(int) 쿠키의 유효 기간 설정
setValue(String) 쿠키 값 설정

 


++ 세션(Session) ++

- 웹 페이지들 사이의 공유 정보를 서버의 메모리에 저장해 놓고 사용하는 방법

- 클라이언트가 웹 애플리케이션 서버에 접속할 때, 서버 쪽에 생성되는 공간

- 내부적으로는 세션 아이디를 통해 참조

  • 브라우저 : 서버에 접속할 때 발급받은 세션 아이디를 기억
  • 서버 : 해당 세션 아이디로 할당된 영역에 접근

- 세션 보안이 쿠키보다 훨씬 높음

 

- 세션 유효 시간이나 브라우저 종료 전까지 유지

- 서로 다른 페이지에서 정보 공유가 가능

- 로그인 유지, 장바구니, 컨트롤러 구현에 사용

- 사용자마다 생성되는 공간    (브라우저(사용자)당 한 개의 세션(세션 id))

 

- 정보가 서버의 메모리에 저장

- 브라우저의 세션 연동은 세션 쿠키를 이용

- 서버에 부하를 줄 수 있음

- 세션은 유효 시간을 가짐(기본 유효 시간 30분)

 

- 세션 실행

  1. 브라우저 : 사이트 접속
  2. 서버 : 접속한 브라우저에 대한 세션 객체 생성
  3. 서버 : 생성된 세션 아이디를 클라이언트 브라우저에 응답
  4. 브라우저 : 서버로부터 받은 세션 아이디를 브라우저가 사용하는 메모리의 세션 쿠키에 저장(쿠키이름 : jsessionId)
  5. 브라우저 재접속-> 브라우저는 세션 쿠키에 저장된 아이디를 서버에 전달
  6. 서버는 세션 아이디를 이용해 해당 세션에 접근해 작업을 수행

- 세션 API

  • 서블릿에서 HttpSession 클래스 객체를 생성해서 사용
  • HttpSession 객체는 HttpServletRequest의 getSession() 메서드로 얻음
  • getSession() : 기존의 세션 객체가 존재하면 반환, 없으면 생성
  • getSession(true) : 기존의 세션 객체가 존재하면 반환, 없으면 생성
  • getSesison(false) : 기존의 세션 객체가 존재하면 반환, 없으면 null 반환
리턴타입 Method Description
Object getAttribute(String name) 속성 이름이 name인 속성을 object로 반환. 없으면 null반환
Enumeration getAttributeNames() 세션 속성 이름을 enumeration 객체 타입으로 반환
long getCreationTime() 1970년1월1일 0시0초를 기준으로, 현재 세션이 생성된 시간까지 경과한 시간을 계산해 1/1000초로 반환
String getId() 세션에 할당된 고유 식별자를 String타입으로 반환
int getmaxInactiveInterval() 현재 생성된 세션을 유지하기 위해 설정된 세션 유지 시간을 int타입으로 반환
void invalidate() 현재 생성된 세션 소멸
boolean isNew() 최초로 생성된 세션인지 판별
void removeAttribute(String name) name 속성 제거
void setAttribute(String name, Object value) name 속성 값으로 value 할당
void  setMaxInactiveInterval(int interval) 세션 유지 시간을 초단위로 설정

 

++ 세션(Session) 트랙킹 ++

     - HTTP 프로토콜은 서버-클라이언트 통신 때 stateless방식으로 통신한다.

           -> 새 웹페이지를 열면, 기존의 어떤 연결 정보도 알 수 없다.

           --> 따라서 세션 트랙킹을 통해 웹 페이지 간의 연결 기능 구현

  •    <hidden> 태그와 URL ReWriting
  •    쿠키와 세션

세션 트랙킹 - <hidden> 태그 실습

// 서블릿
@WebServlet("/login_1_1")
public class LoginServlet_1_1 extends HttpServlet {
	...
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		String user_id = request.getParameter("user_id");
		String user_pw = request.getParameter("user_pw");
		String user_address = request.getParameter("user_address");
		String user_email = request.getParameter("user_email");
		String user_hp = request.getParameter("user_hp");
		
		String data = "<html><body>";
		data += "아이디 : " + user_id;
		data += "<br>";
		data += "비밀번호 : " + user_pw;
		data += "<br>";
		data += "주소 : " + user_address;
		data += "<br>";
		data += "e-mail : " + user_email;
		data += "<br>";
		data += "핸드폰 : " + user_hp;
		data += "</body></html>";
		out.print(data);
	}
}
// html
...
<form name="frmLogin" method="post" action="login_1_1" encType="utf-8">
		아이디 : <input type="text" name="user_id"> <br>
		비밀번호 : <input type="password" name="user_pw"> <br>
		<input type="submit" value="로그인"> <input type="reset" value="다시 입력">
		
		<input type="hidden" name="user_address" value="대전시 서구" />
		<input type="hidden" name="user_email" value="email@naver.com" />
		<input type="hidden" name="user_hp" value="010-0000-0000" />
	</form> ...

<hidden>태그도 출력된다.

하지만 웹 페이지가 많아지면 일일이 로그인 정보를 전송해야 하고, GET 방식으로 전송하므로 보안에 취약함


세션 트랙킹 - URL Rewriting 실습

<body>
	<form name="frmLogin" method="post" action="login_1_2" encType="utf-8">
		...
	</form>
</body>

 

html파일

@WebServlet("/login_1_2")
public class LoginServlet_1_2 extends HttpServlet {
	...
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		...
		
		user_address=URLEncoder.encode(user_address,"utf-8");
		out.print("<a href='/pro09/second_1_2?user_id="+user_id+"&user_pw="+user_pw+
				"&user_address="+user_address+"'>두 번째 서블릿으로 전송</a>");

		data = "</body></html>";
		out.print(data);
	}
}

로그인 서블릿 파일

@WebServlet("/second_1_2")
public class SecondServlet_1_2 extends HttpServlet {
	...
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		String user_id = request.getParameter("user_id");
		String user_pw = request.getParameter("user_pw");
		
		out.println("<html><body>");
		if(user_id!=null && user_id.length()!=0) {
			out.println("이미 로그인되어 있습니다.<br><br>");
			out.println("첫번째 서블릿에서 넘겨준 아이디 : " + user_id + "<br>");
			out.println("첫번째 서블릿에서 넘겨준 비밀번호 : " + user_pw + "<br>");
			out.println("</body></html>");
		} else {
			out.println("로그인 하지 않았습니다. <br><br>");
			out.println("다시 로그인 해주세요.<br>");
			out.println("<a href='/pro09/login_1_2.html'>로그인창으로 이동하기</>");			
		}
	}
}

second 서블릿 파일

초기 화면이다.

두번째 서블릿으로 전송 하이퍼텍스트를 누르면

다시 돌아가서, 로그인을 하지 않은 상태로 

이렇게 출력된다.

 

하지만 웹 페이지가 많아지면 일일이 로그인 정보를 전송해야 하고, GET 방식으로 전송하므로 보안에 취약하다.

권장되지 않는 방법이다.


서블릿에서 쿠키 사용 실습

// set 서블릿
@WebServlet("/set")
public class SetCookieValue extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		Date date = new Date(0);
		
		// 쿠키 객체를 생성하고 cookieTest라는 이름으로 한글 정보를 인코딩하여 쿠키에 저장
		Cookie cookie = new Cookie("cookieTest", URLEncoder.encode("JSP프로그래밍", "utf-8"));
		cookie.setMaxAge(24*60*60);		// 유효기간 설정 (24*60*60초)
		response.addCookie(cookie);
		out.println("현재 시간 : " + date);
		out.println("<br>현재 시간(문자열)을 Cookie로 저장");
	}
}

// get 서블릿
@WebServlet("/get")
public class GetCookieValue extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		Cookie[] allValues = request.getCookies();

		// 배열에서 저장할 때 사용한 쿠키 이름(cookieTest)으로 검색해 쿠키값 가지고 오기
		for(int i=0; i<allValues.length; i++) {
			if(allValues[i].getName().equals("cookieTest")) {
				out.println("<h2>Cookie 값 가져오기 : " + URLDecoder.decode(allValues[i].getValue(), "utf-8"));
			}
		}
	}
}

set부터 생성하고, get

allValues[i].getName() 이 key값 ("cookieTest")이다.

암호화(encoding)와 복호화(decoding) 필수!

Date 객체는 import java.util.Date; (util로 import해야한다.)

set으로 첫번째 서블릿 요청

쿠키에 cookieTest 저장

get으로 두 번째 서블릿 요청

cookieTest로 값을 가져와 출력


세션 쿠키 사용

cookie.setMaxAge(-1);        (cookie.setMaxAge(..)는 삭제해야함) : 유효시간을 음수로 지정하여 Session 쿠키 생성


쿠키로 팝업창 제한하기

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<script type="text/javascript">
	function setPopUpStart(obj) {
		if(obj.checked == true) {
			var expireDate = new Date();
			expireDate.setMonth(expireDate.getMonth() + 1); // 쿠키유효시간 한달
			document.cookie = "notShowPop=" +"true" + ";path=/; expires=" + expireDate.toGMTString();
			window.close();
		}
	}
</script>
</head>
<body>
	알림 팝업창
	<br><br><br><br><br><br><br>
	<form>
		<input type=checkbox onClick="setPopUpStart(this)">오늘 더이상 팝업창 띄우지 않습니다.
	</form>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>자바스크립트에서 쿠키 사용</title>
<script type="text/javascript">
	// 브라우저에 웹페이지가 로드될 때 pageLoad()함수를 호출해 실행
	window.onload = pageLoad; 
	function pageLoad() {
		// notShowPop의 쿠키 값을 getCookieValue()로 얻기
		notShowPop = getCookieValue();
		// notShowPop이 false이면 팝업
		if(notShowPop!="true") {
			window.open("popUp.html", "pop", "width=400, height=500, history=no, resizable=no, status=no, scrollbars=yes, menubar=no");
		}
	}
	function getCookieValue() {
		var result = "false";
		if(document.cookie != "") {
			cookie = document.cookie.split(";");
			for(var i=0; i<cookie.length; i++) {
				element = cookie[i].split("=");
				value = element[0];
				value = value.replace(/^\s*/,'');	// 공백(\s)제거
				if(value == "notShowPop") {
					result = element[1];
				}
			}
		}
		return result;
	}
	function deleteCookie() {
		document.cookie = "notShowPop=" + "false" + ";path=/; expires=-1" ;
	}
</script>
</head>
<body>
	<form>
		<input type=button value="쿠키삭제" onClick="deleteCookie()">
	</form>
</body>
</html>

document.cookir = "notShowPop=" + "true" + ";path=/; expires= 연-월-시";

document.cookie = "notShowPop=" + "false" + ";path=/; expires=-1";         // 쿠키 삭제

 

document.cookie.split(";"); 으로 위의 구문 나눈다

--> 첫번째인덱스-cookie[0]: notShowPop=false      두번째인덱스-cookie[1]: path=/       세번째인덱스-cookie[2]: expires=-1

--> cookie.length: 3

popupTest

파일을 실행시키면, 웹브라우저에 파일이 실행되고

popUp

팝업창이 뜬다. 

체크박스를 체크하면, F5로 다시 불러와도 팝업창이 나오지 않음.

쿠키 삭제 버튼을 눌러 쿠키를 삭제하면, 다시 팝업창이 나온다.


서블릿으로 세션 API 사용 실습

@WebServlet("/sess")
public class SessionTest extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		out.println("세션 아이디 : " + session.getId() + "<br>");
		out.println("최초 세션 생성 시각 : " + new Date(session.getCreationTime()) + "<br>");
		out.println("최근 세션 접근 시각 : " + new Date(session.getLastAccessedTime()) + "<br>");
		out.println("세션 유효 시간 : " + session.getMaxInactiveInterval() + "<br>");
		if(session.isNew()) {
			out.print("새 세션이 만들어졌습니다. ");
		}
	}
}

서블릿 파일

첫번째 탭

최초 요청시 생성된 세션 객체에 할당된 id와 생성시각, 접근 시각, 유효시간 출력

같은 브라우저의 두 번째 탭

최초 생성된 세션을 재사용. 


세션 유효 시간 재설정 실습

@WebServlet("/sess_2")
public class SessionTest_2 extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		out.println("세션 아이디 : " + session.getId() + "<br>");
		out.println("최초 세션 생성 시각 : " + new Date(session.getCreationTime()) + "<br>");
		out.println("최근 세션 접근 시각 : " + new Date(session.getLastAccessedTime()) + "<br>");
		out.println("기본 세션 유효 시간 : " + session.getMaxInactiveInterval() + "<br>");	// 톰캣의 기본 세션 유효시간 
		session.setMaxInactiveInterval(1800);	// 세션의 유효시간을 새로(s) 설정
		out.println("세션 유효 시간 : " + session.getMaxInactiveInterval() + "<br>");	// 재설정한 유효시간
		if(session.isNew()) {
			out.print("새 세션이 만들어졌습니다. ");
		}
	}
}

톰캣 기본 세션의 유효시간

5초후 새로고침했을 때,

재설정한, 새로운 세션


세션  삭제 실습

session.invalidate();

SessionTest_3.java

기다리지 않고,

새로고침(재요청) 하면

바로 새로운 세션이 생성된다.


세션 - 로그인 정보 바인딩 실습

로그인 할 때 로그인 상태를 세션에 저장해서 사용하는 것

 

**톰캣이 종료되어도 세션이 메모리에서 삭제되지 않을 수 있으므로 

Servers-Tomcat v9.0 Server at localhost-config-context.xml에서

<Manager pathname=""/>의 주석을 없애준다.

@WebServlet("/sess_4")
public class SessionTest_4 extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	
	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		
		String user_id = request.getParameter("user_id");
		String user_pw = request.getParameter("user_pw");
		
		if(session.isNew()) {
			if(user_id != null) {
				session.setAttribute("user_id",  user_id);
				out.println("<a href='sess_4'>로그인 상태 확인</a>");
			} else {
				out.print("<a href='login32.html'>다시 로그인 하세요.</a>");
				session.invalidate();
			}
		} else {
			user_id = (String)session.getAttribute("user_id");
			if(user_id != null && user_id.length() != 0) {
				out.print("안녕하세요" + user_id + "님");
			} else {
				out.print("<a href='login32.html'>다시 로그인 하세요.</a>");
				session.invalidate();
			}
		}
	}
}
	<form name="frmLogin" method="post" action="sess_4" encType="utf-8">
		...
	</form>

전달되는 순간 세션은 생성되므로, session.invalidate()으로 세션을 파괴해주어야 한다. 

(잘못로그인 했을 시, 사용할 수 없는 아이디이므로,, 세션을 생성하면 안된다)

 

user_id = (String) session.getAttribute("user_id"); 

-> object형이므로 string형으로 변환해주어야 한다.

아이디와 비밀번호 입력 후, 

최초로 로그인하면, 

세션에 ID 바인딩

로그인 상태  확인을 눌러 /sess_4로 재요청하면,

현재 로그인된 상태를 출력해준다.

톰캣을 종료한 후, 

다시 재실행(/sess_4를)하면, (로그인창을 거치지 않고,)

세션에 ID가 없기 때문에

"다시 로그인하세요" 메세지가 출력된다.


브라우저에서 쿠키 사용 금지하기

크롬에서 설정-쿠키-모두 차단 한 후, 

진행하기

@WebServlet("/sess5")
public class SessionTest5 extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}	 
	
	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 request.setCharacterEncoding("utf-8");
		 response.setContentType("text/html; charset=utf-8"); 
		 PrintWriter out = response.getWriter(); 
		 HttpSession session = request.getSession();
		  
		 String user_id = request.getParameter("user_id"); 
		 String user_pw = request.getParameter("user_pw");
		  
		 if(session.isNew()) { 
			 if(user_id != null) { 
				 session.setAttribute("user_id", user_id); 
				 String url = response.encodeURL("sess5");
				 out.println("<a href="+url+">로그인 상태 확인</a>"); 
			 } else {
				 out.print("<a href='login41.html'>다시 로그인 하세요.</a>"); 
				 session.invalidate(); 
			 }
		 } else { 
			 user_id = (String)session.getAttribute("user_id"); 
			 if(user_id != null && user_id.length() != 0) { 
				 out.print("안녕하세요" + user_id + "님"); 
			 } else {
				 out.print("<a href='login41.html'>다시 로그인 하세요</a>"); 
				 session.invalidate(); 
			 } 
		 }
	 }
}
	<form name="frmLogin" method="post" action="sess5" encType="utf-8">
		...
	</form>

서블릿에 jessionId 쿠키 값을 전송해 로그인 상태를 유지

(URL창)

 

 

 


더보기


replace(치환)

 

var 변수;

변수.replace(,);

 

g : 모든 패턴 체크(global)

i : 대소문자를 구별없이 체크

m : 여러줄 체크

 

^ : 처음

$ : 끝

. : 한문자

 

.replace(' ','')          : 첫번째 공백 제거

.replace(/\-/g,'')        : - 제거

.replace(/[-]/g,'')        

.replace(/,/g,'')         : , 제거

.replace(/^\s+/,'')       : 앞의 공백 제거

.replace(/\s+$/,'')       : 뒤의 공백 제거

.replace(/^\s+|\s+$/g,'') : 앞뒤 공백 제거

.replace(/\s/g,'')        : 문자열 내의 모든 공백 제거

2가지 이상사용시 .replace(/[-]|\s/gi, ''); 등으로 |(or)을 가지고 사용가능 (-,공백제거)

 

(출처 : https://huistorage.tistory.com/20)

 

 

 

(출처 : 짧고 굵게 배우는 JSP 웹 프로그래밍과 스프링 프레임워크(황희정))

댓글