Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 그리디
- QueryDSL
- http
- 자바
- 스프링 핵심 원리
- Proxy
- AOP
- Android
- Exception
- 알고리즘
- kotlin
- JPQL
- springdatajpa
- SpringBoot
- java
- 백준
- 스프링
- 인프런
- Servlet
- Thymeleaf
- 스프링 핵심 기능
- 김영한
- JDBC
- jpa
- db
- transaction
- Greedy
- spring
- pointcut
- Spring Boot
Archives
- Today
- Total
개발자되기 프로젝트
[로그인] 로그인 처리 - 세션 만들기 본문
1. 세션 관리가 제공하는 기능
- 세션 생성
- sessionId 생성 (임의의 추정 불가능한 랜덤 값)
- 세션 저장소에 sessionId와 보관할 값 저장
- sessionId로 응답 쿠키를 생성해서 클라이언트에 전달
- 세션 조회
- 클라이언트가 요청한 sessionId 쿠키의 값으로, 세션 저장소에 보관한 값 조회
- 세션 만료
- 클라이언트가 요청한 sessionId 쿠키의 값으로, 세션 저장소에 보관한 sessionId와 값 제거
2. SessionManager 생성
- cookie 이름은 항상 "mySessionId"임 -> 상수로 만듦 : "SESSION_COOKIE_NAME"
- session은 메모리에 저장하고, 동시성 문제로 인해 ConcurrentHashMap 사용
package hello.login.web.session;
import org.springframework.stereotype.Component;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* 세션 관리
*/
@Component
public class SessionManager {
public static final String SESSION_COOKIE_NAME = "mySessionId";
private Map<String, Object> sessionStore = new ConcurrentHashMap<>();
/**
* 세션 생성
* value와 user 매칭됨.
*/
public void createSession(Object value, HttpServletResponse response){
//session id 생성, 값을 세선에 저장, uuid->univertial unique id
String sessionId = UUID.randomUUID().toString();
sessionStore.put(sessionId, value);
/**
* 쿠키 생성
* new Cookie(name, value)
* value = sessionId
*/
Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
response.addCookie(mySessionCookie);
}
/**
* 세션 조회
* cookie의 이름이 session_cookie_name인 cookie를 가져옴.
*/
public Object getSession(HttpServletRequest request){
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if(sessionCookie == null){
return null;
}
//cookie.getValue() -> SessionId 반환.
return sessionStore.get(sessionCookie.getValue());
}
/**
* 세션 만료
*/
public void expire(HttpServletRequest request){
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if(sessionCookie != null){
sessionStore.remove(sessionCookie.getValue());
}
}
public Cookie findCookie(HttpServletRequest request, String cookieName){
Cookie[] cookies = request.getCookies();
if(cookies == null){
return null;
}
return Arrays.stream(cookies)
.filter(cookie -> cookie.getName().equals(cookieName))
.findAny()
.orElse(null);
}
}
2.1 세션 생성
- sessionStore에 sessionId와 Member를 저장할 예정.
- Member는 Object value로 넘어옴.
- cookie 생성자는 name(cookie 이름)과 value(sessionID, 값)가 필요.
- name – a String specifying the name of the cookie
- value – a String specifying the value of the cookie
- cookie 생성 후 HttpServletResponse에 쿠키 넣어둠.
- 세션 생성 완료
/**
* 세션 생성
* value와 user 매칭됨.
*/
public void createSession(Object value, HttpServletResponse response){
//session id 생성, 값을 세선에 저장, uuid->univertial unique id
String sessionId = UUID.randomUUID().toString();
sessionStore.put(sessionId, value);
/**
* 쿠키 생성
* new Cookie(name, value)
* value = sessionId
*/
Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
response.addCookie(mySessionCookie);
}
2.2 세션 조회
- HttpServletRequest에 쿠키가 담아서 온 경우.
- 넘어온 쿠키 중에 이름이 SESSION_COOKIE_NAME인 쿠키만 필요.
- sessionStore에서 key값인 sessionId로 Member 꺼낼 수 있음.
- sessionCookie의 value는 sessionId임.
/**
* 세션 조회
* cookie의 이름이 session_cookie_name인 cookie를 가져옴.
*/
public Object getSession(HttpServletRequest request){
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if(sessionCookie == null){
return null;
}
//cookie.getValue() -> SessionId 반환.
return sessionStore.get(sessionCookie.getValue());
}
2.3 세션 만료
- 세션 만료 요청이 들어온 경우
- 현재 HttpServletRequest에 쿠키가 있는지 확인.
- 해당 쿠키가 있으면 sessionStore에서 key값인 sessionId로 sessionId와 value(Member)를 지워버림.
/**
* 세션 만료
*/
public void expire(HttpServletRequest request){
Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
if(sessionCookie != null){
sessionStore.remove(sessionCookie.getValue());
}
}
2.4 findCookie()
- HttpServletRequest에서 cookie 배열로 넘어옴.
- Arrays를 활용하면 배열을 stream으로 바꿀 수 있음.
- 이름이 일치하는 쿠키가 가 없으면 null 반환(orElse)
public Cookie findCookie(HttpServletRequest request, String cookieName){
Cookie[] cookies = request.getCookies();
if(cookies == null){
return null;
}
return Arrays.stream(cookies)
.filter(cookie -> cookie.getName().equals(cookieName))
.findAny()
.orElse(null);
}
3. Test
- test를 위해 MockHttpServletRequest, MockHttpServletResponse 사용
- Server -> Client : 세션 생성
- sessionStore에 sessionId, Member저장
- response객체에 쿠키 저장
- cookie -> 이름 : SESSION_COOKIE_NAME, 값 : sessionId
- Client -> Server
- request객체에 response로 받은 쿠키 넣음.
- Server : 세션 조회
- request 객체에서 해당 쿠키 꺼냄.
- 해당 쿠키에서 sessionId를 가지로 sessionStore에서 Member 찾음.
- Server : 세션 만료
- 세션 만료 요청이 들어올 경우
- request 객체에서 해당 쿠키를 찾고.
- 해당 쿠키에서 sessionId를 꺼냄.
- 해당 sessionId를 가지로 sessionStore에서 session삭제
(sessionId, Member 삭제)
class SessionManagerTest {
SessionManager sessionManager = new SessionManager();
@Test
void sessionTest(){
//세션 생성
//가짜 HttpServletResponse
//서버에서 쿠키 생성해서 -> client
MockHttpServletResponse response = new MockHttpServletResponse();
Member member = new Member();
sessionManager.createSession(member, response);
//client가 쿠키 담아서 -> 서버
MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies(response.getCookies());
//세션 조회
Object result = sessionManager.getSession(request);
Assertions.assertThat(result).isEqualTo(member);
//세션 만료
sessionManager.expire(request);
Object expired = sessionManager.getSession(request);
Assertions.assertThat(expired).isNull();
}
}
4. GitHub : 210926 Session
'인프런 > [인프런] 스프링 MVC 2' 카테고리의 다른 글
[로그인] 로그인 처리 - Servlet HTTP 세션 (0) | 2021.09.26 |
---|---|
[로그인] 로그인 처리 - 세션 적용 (0) | 2021.09.26 |
[로그인] 로그인 처리 - 세션 동작 방식 (0) | 2021.09.26 |
[로그인] 쿠키와 보안 문제 (0) | 2021.09.26 |
[로그인] 로그인 처리 - 쿠키 (0) | 2021.09.26 |
Comments