BackEnd/Servlet

9장. 쿠키와 세션 알아보기

제이드Jade 2022. 2. 17. 19:24

9.1 웹 페이지 연결 기능

데이터를 DB에서 가져올 수도 있지만 어떤 정보들은 클라이언트pc나 서버의 메모리에 저장해두고 사용하면 속도향상 할 수 있음. 

 

* HTTP 프로토콜이 각 웹 페이지의 상태나 정보를 다른 페이지들과 공유하지 않는 stateless 방식으로 통신함

 >> 웹 페이지 사이의 상태나 정보를 공유하려면 프로그래머가 세션 트래킹이라는 웹 페이지 연결 기능을 구현해야 함

 

<웹 페이지를 연동하는 방법>

  • <hidden> 태그
  • URL Rewriting : GET 방식으로 URL 뒤에 정보를 붙여서 다른 페이지로 전송
  • 쿠키 : 클라이언트 PC의 Cookie 파일에 정보를 저장 후 공유
  • 세션 : 서버 메모리에 정보를 저장한 후 공유

 

 

9.2 <hidden> 태그와 URL Rewriting 이용해 웹 페이지 연동하기

  • <hidden> 태그 ex)
<form ...
 <input type="hidden" name="user_hp" value="010-111-2222">
</form>

 

  • URL Rewriting ex)

- first

...
user_address=URLEncoder.encode(user_address,"utf-8"); //한글을 전송하기 위한 인코딩
out.print("<br><a href='/pro09/second?user_id="+user_id+"&user_pw="+user_pw+"&user_address="+user_address+"'>두번 째 서블릿으로 보내기</a>");

-second

...
String user_id=request.getParameter("user_id"); // ?로 구분되어 보낸것이 name-value가 됨

 

>>> <hidden>, URLRewritng 방식은 웹 페이지가 많아지면 일일이 정보를 다른 웹페이지로 전송해야하고 특히 URLRewriting은 보안상으로도 좋지 않고 전송할 수 있는 데이터 용량에도 한계가 있다는 단점이 있음. >> 간단한 정보 공유할때만 사용

 

 

9.3 쿠키를 이용한 웹 페이지 연동 기능

  • 쿠키 : 웹 페이지들 사이의 공유 정보를 클라이언트 PC에 저장해 놓고 필요할 대 여러 웹 페이지들이 공유해서 사용할 수 있도록 매개 역할을 하는 방법

 

쿠키 특징

  • 저장 정보 용량에 제한이 있음(파일 용량: 4KB)
  • 보안 취약
  • 클라이언트 브라우저에서 사용 유무를 설정할 수 있음
  • 도메인당 쿠키가 만들어짐(1웹사이트 1쿠키)

 

쿠키의 종류 (Persistence 쿠키, Session 쿠키)

속성 Persistence 쿠키 Session 쿠키
생성 위치 파일로 생성 브라우저 메모리에 생성
종료 시기 쿠키를 삭제하거나 쿠키 설정 값이 종료된 경우 브라우저를 종료한 경우
최초 접속시 전송 여부 최초 접속시 서버로 전송 최초 접속시 서버로 전송되지 않음
용도 로그인 유무 또는 팝업창 제한할 때 사이트 접속시 Session 인증 정보 유지할 때

 

클라이언트 PC에서 쿠키 파일이 생성되는 위치

  • 크롬 : C:\U
  • 인터넷 익스플로어 : 도구>인터넷 옵션>설정>파일보기

 

쿠키 기능 실행 과정

1. 브라우저로 사이트 접속

2. 서버 : 정보를 저장한 쿠키 생성 후 브라우저로 전송

3. 브라우저 : 서버로부터 받은 쿠키 정보를 쿠키 파일에 저장

4.             : 브라우저가 다시 접속해 서버가 브라우저에게 쿠키 전송을 요청할 때 브라우저는 쿠키 정보를 서버에 넘겨줌

5. 서버 : 쿠키 정보를 이용해 작업

 

쿠키 API

  • Cookie 클래스 객체를 생성하여 정보를 저장한 후 서버에서 클라이언트로 전송해 파일로 저장됨
  • HttpServletResponse의 addCookie() : 서버 -> 브라우저, 브라우저는 이를 저장
  • HttpServletRequest의 getCookie() : 브라우저 -> 서버

 

<Cookie 클래스의 여러가지 메서드>

getComment(),  setComment(String) 쿠키에 대한 설명을 가져오고 설정
getDomain(),  setDomain(String) 쿠키의 유효한 도메인 정보
getMaxAge(),  setMaxAge(int) - 쿠키 유효 기간(단위 :초)
- 인자값이 음수이면 Session 쿠키생성 (디폴트)
  인자값이 양수이면 Persistence 쿠키 생성
getName() 쿠키 이름
getPath(), setPath() 쿠키의 디렉토리 정보
getValue(),  setValue(String) 쿠키의 설정 값

 

ex)

set.java

Cookie c=new Cookie("cookieTest",URLEncoder.encode("JSP프로그래밍입니다.","utf-8")); //cookieTest라는 이름으로 내용저장
c.setMaxAge(24*60*60);
response.addCookie(c);

get.java

...
Cookie[] allValues=request.getCookies();

for(int i=0;i<allValues.length;i++) {
    if(allValues[i].getName().equals("cookieTest"))
        out.print("<h2>Cookie 값 가져오기 : "+URLDecoder.decode(allValues[i].getValue(),"utf-8"));
}

 

쿠키 생성 상태 확인하기

F12를 누르고

 

 

세션 쿠키 사용하기

>> 위의 코드에서 c.setMaxAge(-1)처럼 음수로 지정

>> 쿠키를 브라우저 메모리에 저장, 결과는 persistence와 같음

 

쿠키 이용해 팝업창 제한하기

>> 서버가 아닌 자바스크립트를 이용해 쿠키에 직접 접근

 

팝업창.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>팝업창</title>
<script type="text/javascript">
 function setPopUpStart(obj){
	 if(obj.checked==true){
		 var expireDate =new Date();
		 var days=1;
		 expireDate.setDate(expireDate.getDate()+days);  <!-- 팝업쿠키 유효 시간을 하루로 설정 -->
		 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>

뒷화면.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자바스크립트에서 쿠키 사용</title>
<script type="text/javascript">
window.onload=pageLoad; <!-- 브라우저에 페이지가 로드될 때 pageLoad()함수 호출 -->
 function pageLoad(){
	 notShowPop =getCookieValue();
	   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(";"); <!-- document의 cookie 속성으로 쿠키 정보를 문자열로 가지고 옴-->
		 									<!-- 가져온 정보를 ;로 분리해 각각의 쿠키를 얻음 -->
		 for(var i=0;i<cookie.length;i++){
			 element=cookie[i].split("=");
			 value=element[0];
			 value=value.replace(/^\s*/,''); <!-- 정규식을 이용해 쿠키 이름 문자열의 공백(\s)제거 -->
			 if (value=="notShowPop")	<!-- 여러 쿠키 중 notShowPop이름의 쿠키면 값을 가져옴-->
				 result=element[1];
		 }
	 }

	 return result
 }
 function deleteCookie(){
	 document.cookie="notShowPop="+"false"+";path=/; expires=-1"; <!-- 쿠키 삭제 클릭 시 notShowPop 쿠키의 값을 false로 지정 -->
 }
</script>
</head>
<body>
 <form>
  <input type=button value="쿠키삭제" onClick="deleteCookie()">
 </form>
</body>
</html>

 

 

9.4 세션을 이용한 웹 페이지 연동 기능

 

<세션의 특징>

  • 정보가 서버의 메모리에 저장됨
  • 브라우저의 세션 연동은 세션 쿠키를 이용
  • 쿠키보다 보안에 유리
  • 서버에 부하를 줄 수 있음
  • 브라우저당 한 개의 세션(세션id)가 생성
  • 세션은 유효 시간을 가짐(default : 30분)
  • 사용ex) 로그인 상태 유지 기능, 쇼핑몰의 장바구니 기능

 

<세션 기능 실행 과정>

1. 브라우저로 사이트에 접속

2. 서버: 접속한 브라우저에 대한 세션 객체를 생성

3.       : 생성된 세션 id를 클라이언트 브라우저에 응답

4. 브라우저 : 서버로부터 받은 세션 id를 브라우저가 사용하는 메모리의 세션 쿠키에 저장함(쿠키 이름은 jessionId)

5.             : 브라우저가 재접속하면 세션 쿠키에 저장된 세션 id를 서버에 전달

6. 서버 : 전송된 세션 id를 이용해 해당 세션에 접근하여 작업 수행

 

 

<세션 API의 특징과 기능>

  • HttpSession 클래스 객체를 생성해서 사용.
  • HttpServletRequest.geSession() 호출해서 객체 생성

 

<세션을 얻는 getSession() 메서드>

세개 모두 기존의 세션 객체가 존재하면 반환

  • getSession(), getSession(true) : 없으면 새로 생성
  • getSession(false) : 없으면 null 반환

 

<HttpSession 클래스의 여러가지 메서드>

반환 타입 메서드 설명
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, Object value) 세션 속성 이름이 name인 속성 제거
void  setAttribute(String name, Object value) 세션 속성 이름이 name인 value 반환
void setMaxInactiveInterval(int interval) 세션을 유지하기 위한 유지 시간 초단위로 설정

 

~서블릿에서 세션API 이용하기~

...
HttpSession session=request.getSession();

String data="세션 아이디 : "+session.getId();
data+="<br>최초 세션 생성 시각 : "+new Date(session.getCreationTime());
data+="<br>최근 세션 접근 시각 : "+new Date(session.getLastAccessedTime());
data+="<br>세션 유효 시간 : "+session.getMaxInactiveInterval();

out.print(data);

if(session.isNew()) {
    out.print("<br>새 세션이 만들어졌습니다.");
}

>> 브라우저마다 다른 아이디가 출력, 새 브라우저에 최초로 접속할 때만 '새 세션이 만들어졌습니다' 출력됨

F12 눌러서 세션ID 확인하기

 

* 세션 기본 유효 시간 : 톰캣 컨테이너(Servers)의 web.xml 에서 확인 가능

기본 : 30초

* setMaxInactiveInterval(n)로 세션 기본 유효시간 설정 가능

 => 최근 세션 접근 시각+n초마다 새 세션 id로 갱신됨

 => 주로 은행 사이트에서 자주 사용(n분동안 아무 작업도 하지 않으면 로그인 상태를 기억하는 세션이 자동 삭제되어 자동 로그아웃 됨)

 

세션을 이용한 로그인 정보 바인딩 실습

  • 지금까지는 HttpServletContext와 HttpServletRequest의 바인딩 기능을 사용함
  • 로그인 상태처럼 사용자와 관련된 정보를 바인딩해서 사용할 때는 세션을 이용하는 것이 편리

톰캣이 종료된 후에 세션이 메모리에서 삭제되지 않는 경우 방지

  >> 톰캣 설정 파일의 context.xml  <Manager pathname="" /> 태그의 주석을 해제

 

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.print("<a href='login2'>로그인 상태 확인</a>");
    }
    else {
        out.print("<a href='login2.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='login2.html'>다시 로그인 하세요</a>");
    session.invalidate();
}
    }
}

 

 

9.5 encodeURL() 사용법

* 세션도 클라이언트의 세션쿠키를 이용한다.

* but 브라우저에서 쿠키 기능을 사용할 수 없게 설정했다면??

  >> encodeURL()로 직접 서버에서 브라우저로 응답을 보내고 URLRewriting 방법을 이용해서 jessionId를 서버로 전송

* 쿠키가 허용 되었을 때는 처음 요청 응답 때 서버는 jsessionId를 전해주고 클라에 저장하지만

  쿠키가 금지 됐을 때는 저장할 공간(쿠키)가 없기 때문에 처음 응답때 응답만하고 두번째 요청 때 jsessionId를 명시한 url로 연결하여 jsessionId를 서블릿으로 전송함

 

* 크롬에서 쿠키 사용금지하기 : 설정>개인정보 및 보안> 쿠키 및 기타 사이트 데이터 > 쿠키차단

* response.encodeUrl("login2") 로 변수에 미리 jessionId를 저장해놓기

session.setAttribute("user_id", user_id);
String url=response.encodeUrl("login2"); //변수 url에 미리 jessionId를 저장해놓음
out.print("<a href="+url+">로그인 상태 확인</a>");

쿠키금지 시 jessionId가 주소에 명시(금지하지 않으면 x)

 

 

9.6 세션을 이용한 로그인 예제

db와 연동한 후 세션을 이용해 로그인 상태를 유지하기

 => 세션에 로그인 상태 저장해서 각 웹페이지를 열 때마다 세션에서 로그인 상태를 확인한다.

 

- loginServlet

String user_id=request.getParameter("user_id");
String user_pw=request.getParameter("user_pw");

MemberVO memberVO=new MemberVO();
memberVO.setId(user_id);
memberVO.setPwd(user_pw);


MemberDAO dao=new MemberDAO();

if(dao.isExisted(memberVO)) {
    HttpSession session=request.getSession();
    session.setAttribute("isLogon", true);
    session.setAttribute("login.id", user_id);
    session.setAttribute("login.pwd", user_pw);
    out.print("안녕하세요 "+user_id+"님!! <br>");
    out.print("<a href='show'>내정보 보기</a>");
}else {
    out.print("아이디 또는 비밀번호가 틀립니다.<br>");
    out.print("<a href='login3.html'>다시 로그인하기</a>");
}

- DAO

private DataSource dataFactory;
private PreparedStatement pstmt;
private Connection con;

public MemberDAO() {
    try {
        Context ctx=new InitialContext();
        Context envContext=(Context)ctx.lookup("java:/comp/env");
        dataFactory=(DataSource)envContext.lookup("jdbc/oracle");
    }catch(Exception e) {
        e.printStackTrace();
    }
}



public boolean isExisted(MemberVO memberVO) {
    boolean result=false;
    try {
        con=dataFactory.getConnection();
        String query="select decode(count(*),1,'true','false') as result from t_member where id=? and pwd=?";
        //오라클의 decode함수로 조건에 맞는 레코드가 있으면 true, 없으면 false반환
        pstmt=con.prepareStatement(query);
        pstmt.setString(1, memberVO.getId());
        pstmt.setString(2, memberVO.getPwd());

        ResultSet rs=pstmt.executeQuery();
        rs.next(); //커서를 첫번째 레코드로

        result=Boolean.parseBoolean(rs.getString("result")); //result필드 값 얻기

    }catch(Exception e) {
        e.printStackTrace();
    }
    return result;
}

- show

HttpSession session=request.getSession(false);

if(session!=null) {
    if((Boolean)session.getAttribute("isLogon")) {
        String user_id=(String)session.getAttribute("login.id");
        String user_pw=(String)session.getAttribute("login.pwd");
        out.print("아이디 : "+user_id+"<br>비밀번호 : "+user_pw);
    }
    else 
        response.sendRedirect("login3.html");
}else 
    response.sendRedirect("login3.html");
}