본문 바로가기

SPRING

쿠키 @CookieValue

쿠키는 장바구니, 아이디 저장과 같은 상태 정보를 유지하기 위한 기술이다.

대신 보안성이 낮기 때문에 중요한 정보를 넣는 것은 좋지 않다.

 

하나에 4KB 이하로 제한되어 있으며 총 300개까지 정보 저장 가능하며 최대 저장 가능 쿠키 용량은 1.2MB이다.

 

서버에서 쿠키를 만든다.

만든 쿠키를 응답 헤더에 보낸다.

웹 브라우저는 읽은 쿠키를 저장한다.

동일한 요청을 할 때 받은 쿠키를 서버에 보낸다.

서버는 쿠키를 보고 클라이언트가 계속 접속 상태임을 확인한다.

 

@CookieValue

 

메서드 종류

String getName() : 쿠키의 이름 리턴

String getValue() : 쿠키의 값 리턴

String getPath() : 쿠키의 적용 경로 리턴

int getMaxAge() : 쿠키의 유효기간 리턴

 

setValue(String value) : 쿠키의 값 설정

setPath(String path) : 쿠키가 적용되는 경로 지정

ex) setPath("/board") : board 디렉토리와 그 하위 디렉토리 / setPath("/") : 웹 애플리케이션 전체 경로에서 사용 가능

 

setMaxAge(int exp) : 쿠키의 유효시간을 초 단위로 설정

유효기간 미설정 시 웹 브라우저에 저장되며 브라우저를 닫으면 삭제된다.

설정 시에는 사용자의 PC에 저장되며 시간이 지나면 자동으로 삭제된다.

 

 

쿠키 생성

서버에서 쿠키 생성. response의 addCookie 메서드를 이용하여 클라이언트에게 전송

 

// 서버에서 쿠키 생성
Cookie cookie = new Cookie(키, 값);

// 응답에 쿠키 넣어주기
response.addCookie(cookie);

 

클라이언트가 보낸 쿠키 정보 읽기

쿠키는 배열로 return. 즉, 쿠키는 여러 개일 수 있다.

쿠키 값이 없으면 null로 반환. 따라서, null에 대한 처리를 해주어여함.

 

Cookie[] cookies = request.getCookies();

if(cookies != null) { 
	for(Cookie cookie : cookies) { 
    	if("key".equals(cookie.getName())) { 
        	find = true; 
            value = cookie.getValue(); 
        } 
     } 
}

 

클라이언트에게 쿠키 삭제 요청

maxAge를 0으로 설정하면 쿠키 유지 기간이 0인 쿠키가 생성된다. = 사라진다는 뜻

 

cookie.setMaxAge(0);

 

경로 이하에 모두 쿠키 적용

 

cookie.setPath("/");

 

@CookieValue 어노테이션 사용 방법

 

method(@CookieValue(value="쿠키이름", required=false, dafaultValue="기본값") String 변수명)

method(@CookieValue(value="REMEMBER", required=false) Cookie cookie)

 

 

 

로그인 예제에서 아이디를 기억하는 로직을 살펴보자.

 

 

1. LoginVO 클래스 작성

 

package spring;

// 로그인 정보를 담는 VO 클래스
public class LoginCommand {
	
	private String email;
	private String password;
	private boolean rememberEmail; // 이메일 기억하기(쿠키 사용을 위해)
	
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	public boolean isRememberEmail() {
		return rememberEmail;
	}
	
	public void setRememberEmail(boolean rememberEmail) {
		this.rememberEmail = rememberEmail;
	}
	
}

 

2. loginForm.jsp

로그인 폼에 '아이디 기억하기' 영역을 추가

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><spring:message code="login.title"/></title>
</head>
<body>
	<form:form commandName="command"> <!-- controller 요청 파라미터와 맞추기 -->
	<p>
	   <label>
	   <spring:message code="email"/>:
	   <form:input path="email"/>
	   <form:errors path="email"/>
	   </label>
	</p>
	<p>
	   <label>
	   <spring:message code="password"/>:
	   <form:input path="password"/>
	   <form:errors path="password"/>
	   </label>
	</p>
	<p>
	   <label>
	   <spring:message code="rememberEmail"/> <!-- LoginCommand 필드명과 맞추기 -->
	   <form:checkbox path="rememberEmail"/>
	   </label>
	</p>
	<input type="submit" value="<spring:message code="login.btn"/>">
	<form:errors/>
	</form:form>
</body>
</html>

 

3. label.properties에 메세지 추가

 

rememberEmail=아이디 기억하기

 

4. LoginController 작성

 

package controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import spring.AuthInfo;
import spring.AuthService;
import spring.IdPasswordNotMatchingException;
import spring.LoginCommand;
import spring.LoginCommandValidator;

@Controller
@RequestMapping("/login")
public class LoginController {
	
	private AuthService authService;

	public void setAuthService(AuthService authService) {
		this.authService = authService;
	}
	
	@RequestMapping(method=RequestMethod.GET)
	public String form(
		@ModelAttribute("command") LoginCommand loginCommand,
	    @CookieValue(value="REMEMBER", required=false) Cookie cookie) { // 요청에서 쿠키를 확인하기 위한 방법
		
	    if(cookie != null) { // 이미 쿠키가 있으면 (재접속 혹은 쿠키가 유지되는 시간일 경우에 해당)
	       loginCommand.setEmail(cookie.getValue()); // 쿠키의 값을 가져와서 email에 넣어줘
	       loginCommand.setRememberEmail(true); // 쿠키가 존재한다
	    }
	    // 쿠키가 있던 없던 로그인 폼으로 이동
	    return "login/loginForm"; 
	}
	
	 @RequestMapping(method=RequestMethod.POST)
	 public String submit(
	         @ModelAttribute("command") LoginCommand loginCommand, 
	         Errors errors, HttpSession session,
	         HttpServletResponse response) { // 응답 생성
		 
	     new LoginCommandValidator().validate(loginCommand, errors); // 유효성 검사
	     
	     if(errors.hasErrors()) { // 에러가 발생하면 = 아이디나 비번이 비어있으면
	        return "login/loginForm"; // 다시 로그인 폼으로
	     }
	     
	     try {
	        AuthInfo authInfo = authService.authentication(
	              loginCommand.getEmail(), 
	              loginCommand.getPassword());
	        session.setAttribute("authInfo", authInfo); // 인증 정보 세션에 저장
	        
	        // 쿠키 생성
	        Cookie rememberCookie = new Cookie("REMEMBER", loginCommand.getEmail());
	        rememberCookie.setPath("/"); // 해당 경로를 요구할 때만 쿠키를 보내게 함
	        
	        if(loginCommand.isRememberEmail()) { // isRememberEmail()이 true면 = 쿠키가 존재하면
	           rememberCookie.setMaxAge(60); // (60*60*24*30)
	        }else { // isRememberEmail()이 false면
	           rememberCookie.setMaxAge(0); // 쿠키 삭제
	        }
	        
	        response.addCookie(rememberCookie); // 쿠키 전송
	        
	        return "login/loginSuccess"; // 로그인 성공 페이지로 이동
	        
	     } catch(IdPasswordNotMatchingException e) { // 예외가 발생하면
	         errors.reject("idPasswordNotMatching"); // 에러 처리
	         errors.reject("required");
	         return "login/loginForm";
	     }
	}
	 
}