세션이란?
1. 망 환경에서 사용자 간 또는 컴퓨터 간의 대화를 위한 논리적 연결
2. 프로세스들 사이에서 통신을 하기 위해 메시지 교환을 통해 서로를 인식한 이후부터 통신을 마칠 때 까지의 시간이다.
즉, 세션이란 사용자가 웹 브라우저를 통해 웹 서버에 접속한 시점부터(혹은 로그인 시) 그 이후의 요청들은 모두 하나의 상태로 보고 그 상태를 일정시간 유지 시키는 것이다. 이 정보는 웹 서버에 의해 저장되고 관리된다.
쿠키란?
방문자의 정보를 방문자 컴퓨터 메모리에 기억하는 것이다. 예를 들면 로그인 정보(아이디, 비밀번호) 기억 등이 있다.
먼저 세션에 대해 알아보기 위해 로그인 서비스를 만들어보자.
AuthInfo(Long id, String email, String name) 클래스 생성 + 생성자와 getter메소드 만들기
이 AuthInfo 클래스는 로그인 성공 후 인증 상태 정보를 세션에 보관할 때 사용할 클레스이다.
AuthService
package spring;
public class AuthService {
private MemberDao memberDao;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public AuthInfo authenticate(String email, String password) {
Member member = memberDao.selectByEmail(email);
if (member == null) {
throw new WrongIdPasswordException();
}
if (!member.matchPassword(password)) {
throw new WrongIdPasswordException();
}
return new AuthInfo(member.getId(), member.getEmail(), member.getName());
}
}
위와 같이 이메일과 비밀번호가 일치하는지 확인해서 AuthInfo 객체를 생성하는 AuthService 클래스를 만든다.
즉, 로그인 처리 기능을 하고, HttpSession으로 활용할 AuthInfo 객체를 반환하는 클래스라고 생각.
추가적으로, 폼에서 로그인 정보를 받을 커맨드 객체와 커맨드 객체 검증 Validator를 만들어주자.
커멘드 객체: LoginCommand(String email, String password, bollean rememberEmail) + getter, setter
커맨드 검증 객체: LoginCommandValidator -> email과 password에 rejectIfEmptyOrWhitespace메소드를 걸고
"required" 오류코드를 걸어주자.
loginForm.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<%@ page contentType="text/html; charset=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>
<title><spring:message code="login.title" /></title>
</head>
<body>
<form:form modelAttribute="loginCommand">
<form:errors />
<p>
<label><spring:message code="email" />:<br>
<form:input path="email" />
<form:errors path="email"/>
</label>
</p>
<p>
<label><spring:message code="password" />:<br>
<form:password path="password" />
<form:errors path="password"/>
</label>
</p>
<p>
<label><spring:message code="rememberEmail" />:
<form:checkbox path="rememberEmail"/>
</label>
</p>
<input type="submit" value="<spring:message code="login.btn" />">
</form:form>
</body>
</html>
|
cs |
로그인 폼에서는 커맨드 객체인 loginCommand를 활용하여 <form:form>태그를 통해 폼을 작성한 모습이다.
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import spring.AuthInfo;
import spring.AuthService;
import spring.LoginCommand;
import spring.LoginCommandValidator;
import spring.WrongIdPasswordException;
@Controller
@RequestMapping("/login")
public class LoginController {
private AuthService authService;
public void setAuthService(AuthService authService) {
this.authService = authService;
}
@GetMapping
public String form(LoginCommand loginCommand, @CookieValue(value = "REMEMBER", required = false) Cookie rCookie) {
if (rCookie != null) {
loginCommand.setEmail(rCookie.getValue());
loginCommand.setRememberEmail(true);
}
return "login/loginForm";
}
@PostMapping
public String submit(LoginCommand loginCommand, Errors erorrs, HttpSession session, HttpServletResponse response) {
new LoginCommandValidator().validate(loginCommand, erorrs);
if (erorrs.hasErrors()) {
return "login/loginForm";
}
try {
AuthInfo authInfo = authService.authenticate(loginCommand.getEmail(), loginCommand.getPassword());
session.setAttribute("authInfo", authInfo);
Cookie rememberCookie = new Cookie("REMEMBER", loginCommand.getEmail());
rememberCookie.setPath("/");
if (loginCommand.isRememberEmail()) {
rememberCookie.setMaxAge(60 * 60 * 24 * 30);
} else {
rememberCookie.setMaxAge(0);
}
response.addCookie(rememberCookie);
return "login/loginSuccess";
} catch (WrongIdPasswordException e) {
erorrs.reject("idPasswordNotMatching");
return "login/loginForm";
}
}
}
HttpSession 생성 방법
첫번째 방법: 요청 매핑 메서드의 파리미터에 HttpSession을 추가한다.
스프링 MVC는 컨트롤러의 메서드를 호출할 때 HttpSession 객체를 파라미터로 자동 전달한다. HttpSession이 아직 생성이 안되어 있으면 새로운 HttpSession을 생성한다.
두번째 방법: 요청 매핑 메서드의 파라미터에 HttpServletRequest를 추가하고,
HttpSession session = request.getSession; 을 실행한다. 이 방법은 필요한 시점에만 HttpSession을 생성할 수 있다는 장점이 있다.
HttpSession에 만들어진 authInfo 값을 저장해야 한다. session.setAttribute("authInfo", authInfo); (48행)
"authInfo" 속성에 authInfo 값을 넣었다. 로그인이 완료되고 다른 페이지에서 이 세션이 유지가 되는지 확인해보자.
main.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>메인</title>
</head>
<body>
<c:if test="${ empty authInfo }">
<p>환영합니다.</p>
<p>
<a href="<c:url value="/register/step1"/>">[회원 가입하기]</a><br>
<a href="<c:url value="/login" />">[로그인]</a>
</p>
</c:if>
<c:if test="${! empty authInfo }">
<p>${authInfo.name}님 환영합니다.</p>
<p>
<a href="<c:url value="/edit/changePassword" />">[비밀번호 변경]</a><br>
<a href="<c:url value="/logout" />">[로그아웃]</a>
</p>
</c:if>
</body>
</html>
|
cs |
main에서 authInfo가 비어있을 때, 안비어있을 때를 구분해서 페이지를 작성했다. 즉 로그인하고 이 페이지를 보는것과 안하고 보는 화면이 다르다는 것이다.
로그인하기전

로그인한 후
이렇게 등장할 수 있는 이유은 Session에 AuthInfo의 정보를 담았기 때문이다.
로그아웃(세션만료) 시키기
LogoutController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LogoutController {
@RequestMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/main";
}
}
|
cs |
session. invalidate(); 하면 끝이다.
쿠키 설정
우리는 LoginCommand객체를 만들 때 불린형 rememberEmail 필드를 생성했었다.
로그인 시 아이디 기억하기 버튼을 누르면 쿠키에 저장되어 폼에 아이디가 자동 생성되어 있는 기능을 만들어보자.
1. 쿠키를 사용하는 설정
2. 쿠키를 생성하는 설정
쿠키를 만들기 위해선 위 두가지 설정을 모두 해야한다.
쿠키 사용 설정 - (폼에서 기억한 이메일을 보여줌)
@CookieValue 어노테이션을 적용하면 쉽게 쿠키를 요청 매핑 메소드의 쿠키 파라미터로 전달받을 수 있다.
위의 LoginController 참고
31행: @CookieValue(value ="REMEMBER", required=false) Cookie rCookie
value속성: 전달받을 쿠키의 이름을 지정한다.
required속성: 지정한 이름을 가진 쿠키가 존재하지 않을 수도 있다면 이 값을 false로 하자. (기본값 true)
32행: 쿠키가 존재하면
33행: 뷰 jsp에 전달할 커맨드 객체의 Email 속성에 쿠키 값을 전달한다. 쿠키 값 호출함수: Cookie.getValue()
쿠키 생성 설정 - (사용자가 로그인을 완료하면 해당 Response를 읽어와서 Response에 쿠키를 저장)
40행: HttpServletResponse response 파라미터
50행: Cookie rememberCookie = new Cooke("REMEMBER", loginCommand.getEmail()); => 쿠키 생성
51행~56행: 쿠키 경로 설정, 이메이 기억 체크박스 체크확인, 쿠키 유지시간 설정(30일)
57행: response.addCookie(resmemberCookie); 리스폰스에 쿠키 추가
깨알영어
authentic: 진본인, 진품인
authenticate: 진짜임을 증명하다.