세션을 이용한 로그인의 동작원리
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값을 반환해 인증이 필요함을 알립니다.
GitHub - gwjeondev/loginTest
Contribute to gwjeondev/loginTest development by creating an account on GitHub.
github.com
아래 블로그를 따라 구현했습니다.
로그인 구현 - 쿠키와 세션
로그인 구현 - 쿠키와 세션
velog.io
'Spring' 카테고리의 다른 글
Spring Security 모든 인증된 사용자의 세션 확인 (0) | 2023.05.26 |
---|---|
Session을 이용한 로그인2(HttpServletRequest이용) (0) | 2023.05.20 |
세션고정 취약점 및 보호 정책 (0) | 2023.05.18 |
LAZY로딩 관련 정리(직렬화 오류, N+1문제) (0) | 2023.05.11 |
JWT인증 설정 시 SpringBootTest (0) | 2023.05.06 |