[Spring Boot] 로그인 기능 구현 (2) - 세션 로그인

2024. 1. 7. 15:23· Spring Boot
목차
  1.  
  2. 1. 세션 (Session) 이란 ?
  3. 2. 세션 생성, 추가, 읽기
  4. 2-1. 세션 생성
  5. 2-2. 세션 속성 설정
  6. 2-3. 세션 정보 읽기
  7. 2-4. 세션 삭제
  8. 3. 로그인 프로젝트에 적용
  9. 3-1. SessionLoginController
  10. 4. 실행결과

2024.01.07 - [Spring Boot] - [Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현

 

[Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현

0. 상황 설명 여러가지 방법을 사용해서 로그인 기능을 구현하려 함 공통인 기능과 코드는 이 게시글에서 모두 정리 방법마다 다른 코드는 각 게시물에서 따로 정리 1. 프로젝트 버전 정보 / DB 스

blogan99.tistory.com

 

1. 세션 (Session) 이란 ?

  • 웹사이트를 이용할 때 쓰는 프로토콜인 HTTP는 stateless '무상태' 임
    • stateless : 서버로 전달되는 모든 request는 이전 request와는 독립적으로 다뤄짐 (관계없음)
  • 따라서 request가 끝나면 서버는 클라이언트가 누구인지 모르기 때문에 모든 request에 클라이언트의 정보를 넘겨줘야 함
  • 이를 수행하는 방법 중 하나가 세션 (Session) 임
  • 즉, 세션이란 서버에서 클라이언트의 상태를 유지하기 위한 메커니즘
  • 회원가입을 하면 서버는 세션 DB에 해당 계정의 정보를 저장함 (세션은 고유한 세션 ID가 존재)
  • 세션 ID는 쿠키와 같은 매개채를 통해서 브라우저, 클라이언트에 전달, 저장됨
  • 브라우저는 해당 페이지에서 다른 request를 할 때마다 세션 ID가 포함된 쿠키를 매번 서버에 전달함
  • 서버에서는 매번 세션 ID를 통해서 세션 DB에 데이터가 있는지 확인함
  • 이로 인한 단점은
    • request가 발생할 때마다 DB에서 데이터를 검색해야 함 => 데이터가 많을 수록 비효율적
    • 사용자가 많아지면 그에 따른 세션 ID를 저장해야할 세션 DB의 용량이 커지게 됨

 

2. 세션 생성, 추가, 읽기

  • HttpSession 인터페이스를 사용

 

2-1. 세션 생성

  • 자동으로 세션 생성
    • 웹 애플리케이션에서 세션은 사용자의 첫 요청이 들어올 때 자동으로 생성됨
  • 명시적으로 세션 생성
    • HttpServletRequest 객체를 통해 세션 생성
@RequestMapping("")
public String session(HttpServletRequest request){
	
    // request 에 대한 세션을 가져옴
    // true : 세션이 없다면 새로운 세션 생성해서 리턴
    // false : 세션이 없다면 null 리턴
   	HttpSession session = request.getSession(true);
    
    ...
}

 

2-2. 세션 속성 설정

  • setAttribute 메서드는 "키", "값" 쌍의 형태로 세션에 저장함
  • 저장된 속성은 세션의 유효 기간 동안 유지, 같은 사용자의 다른 요청에서도 사용 가능
// 키, 값 쌍으로 세션에 속성 추가
session.setAttribute("키", "값");

// 세션의 유효 기간 설정 => 1시간
session.setMaxInactiveInterval(60 * 60);

 

2-3. 세션 정보 읽기

  • getAttribute
@RequestMapping("")
public String getSessionAttribute(HttpSession session){
	
    // 세션에 담겨있는 속성 중 "키"라는 이름의 "값"을 가져옴
    String value = session.getAttribute("key");
    
    ...
}
  • @SessionAttribute
@RequestMapping("")
public String getSessionAttribute(@SessionAttribute(name = "키", required = false) String value){
    
    // @SessionAttribute 를 통해서 value 변수 안에 세션의 속성 중 "키" 이름을 가진 값이 저장됨
    
    ...
}

 

2-4. 세션 삭제

  • 세션 삭제 방법은 크게 두 가지
    • 세션의 모든 속성을 제거하는 방법
    • 세션을 무효화 하는 방법

 

2-4-1) 세션 속성 제거

// 세션에서 "키"라는 이름의 세션 속성 제거
session.removeAttribute("키");

 

2-4-2) 세션 무효화

// 세션 무효화 : 세션에 저장된 모든 데이터 삭제, 세션 종료
session.invalidate();

 

3. 로그인 프로젝트에 적용

  • 로그인을 제외한 나머지 기능, 라이브러리 등은 아래 게시글 참고

2024.01.07 - [Spring Boot] - [Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현

 

[Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현

0. 상황 설명 여러가지 방법을 사용해서 로그인 기능을 구현하려 함 공통인 기능과 코드는 이 게시글에서 모두 정리 방법마다 다른 코드는 각 게시물에서 따로 정리 1. 프로젝트 버전 정보 / DB 스

blogan99.tistory.com

 

3-1. SessionLoginController

  • home
    @GetMapping(value = {"", "/"})
    public String home(Model model, @SessionAttribute(name = "memberId", required = false) Long memberId) {
        
        // 화면에 출력하기 위해 model에 속성 추가
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        Member loginMember = memberService.getLoginMemberById(memberId);
        
        // 로그인 되어있다면 model에 이름 속성 추가
        if (loginMember != null) {
            model.addAttribute("name", loginMember.getName());
        }

        return "home";
    }
  • @SessionAttribute를 통해서 세션의 값 읽어옴
    • 세션의 name에 해당하는 값이 존재한다면 로그인 한 것 => model에 속성 추가
    • 존재하지 않으면 로그인 하지 않은 것 => model에 name이 null로 들어있음

 

  • join
    @GetMapping("/join")
    public String joinPage(Model model) {
    
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");
        
        // 회원가입을 위해서 model 통해서 joinRequest 전달
        model.addAttribute("joinRequest", new JoinRequest());
        return "join";
    }

    @PostMapping("/join")
    public String join(@Valid @ModelAttribute JoinRequest joinRequest, 
                       BindingResult bindingResult, Model model) {

        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        // ID 중복 여부 확인
        if (memberService.checkLoginIdDuplicate(joinRequest.getLoginId())) {
            bindingResult.addError(new FieldError("joinRequest", "loginId", "ID가 존재합니다."));
        }


        // 비밀번호 = 비밀번호 체크 여부 확인
        if (!joinRequest.getPassword().equals(joinRequest.getPasswordCheck())) {
            bindingResult.addError(new FieldError("joinRequest", "passwordCheck", "비밀번호가 일치하지 않습니다."));
        }

        // 에러가 존재할 시 다시 join.html로 전송
        if (bindingResult.hasErrors()) {
            return "join";
        }

        // 에러가 존재하지 않을 시 joinRequest 통해서 회원가입 완료
        memberService.join(joinRequest);
        
        // 회원가입 시 홈 화면으로 이동
        return "redirect:/session-login";
    }
  • 쿠키 사용한 로그인과 동일 ( https://blogan99.tistory.com/84 )

 

  • login
    @GetMapping("/login")
    public String loginPage(Model model) {
        
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        model.addAttribute("loginRequest", new LoginRequest());
        return "login";
    }

    @PostMapping("/login")
    public String login(@ModelAttribute LoginRequest loginRequest, BindingResult bindingResult,
                        HttpServletRequest request, Model model) {
                        
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        Member member = memberService.login(loginRequest);
        
        // ID나 비밀번호가 틀린 경우 global error return
        if (member == null) {
            bindingResult.reject("loginFail", "로그인 아이디 또는 비밀번호가 틀렸습니다.");
        }

        if (bindingResult.hasErrors()) {
            return "login";
        }

        // ===== 로그인 성공 => 세션 생성 및 속성 설정 =====
        
        // 기존의 세션을 무효화
        request.getSession().invalidate();
        
        // 세션 생성 => request에 연관된 세션이 없을 시 새로운 세션 생성 후 반환
        HttpSession session = request.getSession(true);
        
        // 세션에 {"memberId", memberId} 속성 추가
        session.setAttribute("memberId", member.getId());
        
        // 세션의 유효기간을 1시간으로 설정
        session.setMaxInactiveInterval(60 * 60);

        // =========================================
        
        return "redirect:/session-login";
    }
  • @ModelAttribute로 받아온 데이터로 로그인 진행
    • 쿠키 로그인과 동일 ( https://blogan99.tistory.com/84 )
  • 로그인 성공 시 세션 생성, 속성 설정
    • 세션에 Id값 저장, 유효기간 1시간으로 설정

 

  • logout
    @GetMapping("/logout")
    public String logout(HttpServletRequest request, Model model) {
    
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        // request와 연관된 세션 불러옴 (없으면 null 반환)
        HttpSession session = request.getSession(false);
        
        // 세션이 존재 ( : 로그인 되어있다는 뜻)
        if (session != null) {
            // 로그인 된 세션 무효화
            session.invalidate();
        }

        return "redirect:/session-login";
    }
  • session.invalidate()를 통해서 로그아웃 구현

 

  • info
    @GetMapping("/info")
    public String memberInfo(@SessionAttribute(name = "memberId", required = false) Long memberId, Model model) {
        
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션로그인");

        Member loginMember = memberService.getLoginMemberById(memberId);

        if (loginMember == null) {
            return "redirect:/session-login/login";
        }

        model.addAttribute("member", loginMember);
        return "info";
    }

 

  • admin
    @GetMapping("/admin")
    public String adminPage(@SessionAttribute(name = "memberId", required = false) Long memberId, Model model) {
        
        model.addAttribute("loginType", "session-login");
        model.addAttribute("pageName", "세션 로그인");

        Member loginMember = memberService.getLoginMemberById(memberId);

        if(loginMember == null) {
            return "redirect:/session-login/login";
        }

        if(!loginMember.getRole().equals(MemberRole.ADMIN)) {
            return "redirect:/session-login";
        }

        return "admin";
    }
}

 

4. 실행결과

  • 홈 화면

  • 회원가입 화면

  • 회원가입 화면 (오류)

  • 로그인 화면

  • 로그인 화면 (오류)

  • 로그인 후 홈 화면

  • 마이 페이지

  • 관리자 계정으로 로그인 후 관리자 페이지

 

  • 쿠키의 값이 변경됨
    • 로그인 함으로써 세션ID가 쿠키를 통해서 전달됨을 확인

저작자표시 변경금지 (새창열림)

'Spring Boot' 카테고리의 다른 글

[Spring Boot] 스프링으로 엑셀 파일 읽기  (1) 2024.01.08
[Spring Boot] 로그인 기능 구현 (3) - 스프링 시큐리티 로그인  (4) 2024.01.07
[Spring Boot] 로그인 기능 구현 (1) - 쿠키 로그인  (0) 2024.01.07
[Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현  (2) 2024.01.07
[Spring Boot] 페이징 기능 구현 ( + 페이징, 정렬, 검색, 에러 메시지 포함 예제)  (1) 2024.01.03
  1.  
  2. 1. 세션 (Session) 이란 ?
  3. 2. 세션 생성, 추가, 읽기
  4. 2-1. 세션 생성
  5. 2-2. 세션 속성 설정
  6. 2-3. 세션 정보 읽기
  7. 2-4. 세션 삭제
  8. 3. 로그인 프로젝트에 적용
  9. 3-1. SessionLoginController
  10. 4. 실행결과
'Spring Boot' 카테고리의 다른 글
  • [Spring Boot] 스프링으로 엑셀 파일 읽기
  • [Spring Boot] 로그인 기능 구현 (3) - 스프링 시큐리티 로그인
  • [Spring Boot] 로그인 기능 구현 (1) - 쿠키 로그인
  • [Spring Boot] 로그인 기능 구현 (0) - 공통 기능, 코드 구현
공대생안씨
공대생안씨
전자공학과 학부생의 코딩 일기
티스토리
|
로그인
공대생안씨
공대생의 코딩 일기
공대생안씨
글쓰기
|
관리
전체
오늘
어제
  • All Categories (153)
    • Spring Boot (46)
      • JPA (7)
      • Lombok (2)
    • Java (21)
    • DevOps (3)
      • CI,CD (8)
      • Monitoring (2)
    • Database (7)
      • MySQL (5)
      • MongoDB (1)
      • H2 (1)
    • Trouble Shooting (5)
    • FE (4)
    • IntelliJ (3)
    • Git (3)
    • Algorithm (41)

블로그 메뉴

  • 홈
  • 태그
  • Github

공지사항

인기 글

hELLO · Designed By 정상우.v4.2.2
공대생안씨
[Spring Boot] 로그인 기능 구현 (2) - 세션 로그인
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.