Spring

Session을 이용한 로그인1(직접 구현)

Seung__Yong 2023. 5. 20. 02:26

세션을 이용한 로그인의 동작원리

1. 인증에 성공했을 때 세션생성(SessionStore에 Map(SessionId, Session)의 형태로 관리

2. 세션에 Map("LOGIN_MEMBER", loginObject)의 형태로 저장

3. response에 sessionId가진 쿠키("JSESSION_ID", sessionId)를 담아 반환

 

4. 클라이언트는 자원 요청시 쿠키를 가지고 접근

5. 쿠키에 담긴 세션아이디가 서버의 저장소에 존재한다면 세션객체 반환

6. 세션에서 "LOGIN_MEMBER"에 매칭되는 loginObject 반환

-> 이렇게 반환 받은 로그인 객체를 이용하여 인증을 유지합니다. 

 

구현

세션의 이해를 돕기위해 직접 Session을 관리하는 SessionManager클래스를 구현해 로그인을 진행해보았습니다. 

@Controller
@RequiredArgsConstructor
public class MemberController {
    private final SessionManager sessionManager;
    private final MemberService memberService;
    @GetMapping("/")
    public String home(HttpServletRequest request, Model model) {
        Session session = sessionManager.getSession(request);

        if(session == null) { // 아직 인증 X
            return "login";
        }

        Member loginMember = (Member) session.getAttribute("LOGIN_MEMBER");
        model.addAttribute("member", loginMember);
        return "home";
    }

    @PostMapping("/login")
    public String login(@ModelAttribute MemberDto memberDto, HttpServletResponse response){
        Member loginMember = memberService.login(memberDto);

        if(loginMember == null) // 로그인 실패
            return "redirect:/"; // 세션없이 홈으로 이동 -> 로그인 페이지 이동

        Session session = sessionManager.createSession(loginMember, response);// 세션 생성
        session.setAttribute("LOGIN_MEMBER", loginMember); // 세션에 로그인 객체 저장

        return "redirect:/"; // 세션이 존재하므로 home으로 이동
    }

    @PostMapping("logout")
    public String logout(HttpServletRequest request) {
        sessionManager.sessionExpire(request);
        return "redirect:/";
    }
}

로그인을 시도했을 때 처리과정은 다음과 같습니다.

1. 로그인 성공 시 -> 세션에 로그인 객체 저장 후 "/"으로 이동 -> 세션이 존재하기 때문에 "home"으로 이동

2. 로그인 실패 시 -> 세션없이 "/"로 이동 -> "login"으로 이동

 

구현한 SessionMager클래스는 다음과 같습니다.

@Component
@RequiredArgsConstructor
public class SessionManager {
    private String SESSION_ID_NAME = "JSESSION_ID";
    private final HashMap<String, Session> sessionStore;

    public Session createSession(Member value, HttpServletResponse response)
    {
        String token = UUID.randomUUID().toString(); // sessionId 생성
        Session session = new Session();
        sessionStore.put(token, session); // 세션에 데이터 저장
        Cookie cookie = new Cookie(SESSION_ID_NAME, token); // LOGIN_MEMBER라는 이름을 가지고 세션아이디를 담은 쿠키
        response.addCookie(cookie); // 쿠키 response에 담기

        return session;
    }
    public Session getSession(HttpServletRequest request){
        Cookie sessionCookie = findCookie(request);
        if(sessionCookie == null)
            return null;

        return sessionStore.get(sessionCookie.getValue());
    }
    public Cookie findCookie(HttpServletRequest request){
        if(request.getCookies() == null)
            return null;

        return Arrays.stream(request.getCookies())
                .filter(cookie -> cookie.getName().equals(SESSION_ID_NAME)) // 세션아이디를 담은 쿠키 조회
                .findFirst()
                .orElse(null);
    }

    public void sessionExpire(HttpServletRequest request) {
        Cookie sessionCookie = findCookie(request);
        if(sessionCookie != null) {
            sessionStore.remove(sessionCookie.getValue());
        }
    }
}

1. 쿠키를 조회해 세션아이디가 존재하는지 확인합니다.

2. 기존 세션이 존재한다면 반환해줍니다.

3. 없다면 null값을 반환해 인증이 필요함을 알립니다.

 

 

 

* 전체코드 https://github.com/gwjeondev/loginTest/blob/master/src/main/java/login/logintest/web/controller/LoginController.java

 

GitHub - gwjeondev/loginTest

Contribute to gwjeondev/loginTest development by creating an account on GitHub.

github.com

 

아래 블로그를 따라 구현했습니다.

https://velog.io/@won-developer/%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84-%EC%BF%A0%ED%82%A4%EC%99%80-%EC%84%B8%EC%85%98-n3wwrtip

 

로그인 구현 - 쿠키와 세션

로그인 구현 - 쿠키와 세션

velog.io