Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
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
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[로그인] 로그인 처리 - 세션 만들기 본문

인프런/[인프런] 스프링 MVC 2

[로그인] 로그인 처리 - 세션 만들기

Seung__ 2021. 9. 26. 11:08

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


 

GitHub - bsh6463/login

Contribute to bsh6463/login development by creating an account on GitHub.

github.com

 

Comments