Java - Spring &&n SpringBoot

spring - 로그인 기능 구현하기 (3) HTTP서블릿 세션 활용하기

TerianP 2022. 1. 29.
728x90

대망의 spring 로그인 기능 구현하기 3번째 내용입니다.

이번 시간으로 해서 로그인 기능에 관한 것은 마치겠습니다!!

 

1. Session : 세션을 직접 만든다?! NO NO!!

사실 이전 세션을 활용한 로그인 구현의 내용은 정말로 내가 직접 세션으로서 동작할 수 있도록 기능을 '만들어서' 로그인 할 수 있도록 했다. 그런데 사실 모든 사이트에서 매번 이렇게 세션을 직접 만들어서 사용하는 것은 굉장히...골아프고 힘든 일이다. 이에 HTTP 서블릿 에서 HttpSession 을 제공한다. 이번에는 이를 활용해서 로그인 하는 기능을 만들어보겠다.

 

1) HttpSession

HTTP서블릿에서 지원하는 HttpSession 은 다음과 같은 특징을 갖는다.

  • 이전에 만들었던 SessionManager 와 같은 방식으로 동작한다. 즉, 우리가 따로 만들어줄 필요가 없다.
  • 서블릿을 통해 HttpSession 을 생성하면 다음과 같은 쿠키를 생성한다.
    • 쿠키 이름은 JSESSIONID, 값은 역시 추정불가능한 UUID 값

 

2) 코드로 구현하기

request.getSession(true, false) 차이

  • request.getSession(true)
    • 세션이 있으면 기존 세션 반환
    • 세션이 없으면 새로운 세션 생성해서 반환
  • request.getSession(false)
    • 세션이 있으면 기존 세션 반환
    • 세션이 없으면 새로운 세션 생성 X => null 반환
    • 홈페이지에 처음 들어온 사람이며 로그인 안한 사람의 경우 세션을 만들 필요가 없고 이때 false 가 사용됨

 

2. JSesssionID 사용하기

http 서블릿에서 지원하는 session 기능을 사용하기 위해 새로운 homeController 와 LoginController 을 만들어줍니다.

 

- new_homeController

package HJproject.Hellospring.Controller;


import HJproject.Hellospring.Session.SessionConst;
import HJproject.Hellospring.Session.SessionManager;
import HJproject.Hellospring.domain.member.Member;
import HJproject.Hellospring.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Optional;


@Controller
@RequiredArgsConstructor
public class new_HomeController {

    private final MemberRepository memberRepository;

//    @GetMapping("/") // 직접 만든 세션을 사용한 로그인
    public String LoginHomeWithHttpSession(HttpServletRequest request, Model model) {
        // 로그인 안했을 시
        HttpSession session = request.getSession(false);

        if(session == null){
            return "newspringhome";
        }

        /* 로그인 시도 시 */
        Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);

        if(loginMember.getCode() == null){

            // 각각 로그인을 시도했으나 회원 코드가 없는 경우, 회원코드가 0 인 경우, 회원 코드가 0 이 아닌 경우
            return "newspringhome";

        }else if(loginMember.getCode() == 0){
            session.getAttribute(session.getId());
            model.addAttribute("member", loginMember);
            System.out.println("관리자 로그인 성공");

            /** 이런식으로 session에 담아져있는 값을 가져올 수 있음 */
            System.out.println(session.getAttribute("memberCode"));

            /** 이런식으로 세션 토큰 값을 가져올 수 있음 **/
            System.out.println("JSESSIONID :"+request.getRequestedSessionId());

            return "newspringhome_admin";

        }else {
            model.addAttribute("member", loginMember);
            System.out.println("일반 회원 로그인 성공");
            System.out.println("JSESSIONID :"+request.getRequestedSessionId());
            return "newspringhome_login";
        }


    }

    @GetMapping("/") // 스프링이 지원하는 세션 기능 : @SessionAttribute
    public String LoginHomeWithHttpSessionv2(
            // 기능은 이전과 동일. 즉 SessionConst.LOGIN_MEMBER 참고하여 세션 유무 확인 후 없으면 null 반환
            // 로그인 하면 member 에 담은 것 활용해서 로그인 세션 기능 제공
            @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {

        // 로그인 안했을 시
        // 스프링이 알아서 처리해줌 만세!

        /* 로그인 시도 시 */
        // 각각 로그인을 시도했으나 회원 코드가 없는 경우, 회원코드가 0 인 경우, 회원 코드가 0 이 아닌 경우
        if(loginMember == null){

            return "newspringhome";

        }else if(loginMember.getCode() == 0){

            model.addAttribute("member", loginMember);
            System.out.println("관리자 로그인 성공");

            return "newspringhome_admin";

        }else {
            model.addAttribute("member", loginMember);
            System.out.println("일반 회원 로그인 성공");
            return "newspringhome_login";
        }


    }

}

 

- new_LoginController

package HJproject.Hellospring.Controller;

import HJproject.Hellospring.Session.SessionConst;
import HJproject.Hellospring.Session.SessionManager;
import HJproject.Hellospring.domain.login.LoginForm;
import HJproject.Hellospring.domain.member.Member;
import HJproject.Hellospring.service.LoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Slf4j
@Controller
@RequiredArgsConstructor // 클래스의 final 필드에 대한 생성자를 자동으로 생성
public class new_LoginController {

    private final LoginService loginService;
    private final SessionManager sessionManager; // @Component 필요

    @GetMapping("/login")
    public String LoginForm(@ModelAttribute("LoginForm")LoginForm form){
        return "members/login";
    }

    @PostMapping("/login") // http 서블릿 세션 활용 로그인
    public String loginWithHttpSession(@ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
            return "members/login";
        }

        // 1. loginForm 을 통해 값들을 가져옴
        Member LoginMember = loginService.login(form.getLoginid(), form.getLoginpw());

        if (LoginMember == null) { // login 메서드에서 던져주는 값이 null 이면 로그인 실패
//            bindingResult.reject("login Fail", "아이디 또는 비밀번호가 맞지 않습니다");
            System.out.println("로그인 실패");
            return "members/login";
        }

        // 2. null 이외의 값 즉 member 객체라면 로그인 성공 처리

        // http 서블릿 세션을 활용하기 위해서는 httpservlerequest 가 필요함 : 세션이 있으면 세션 반환, 없으면 세션 생성
        // 이때 request.getSession() 에서 getSession() 의 파라미터안에는 true, false 두가지가 올 수 있음
        HttpSession session = request.getSession();

        // 세션에 회원 정보(LoginMember) 저장 후 홈으로 반환
        session.setAttribute(SessionConst.LOGIN_MEMBER, LoginMember);

        /** 이렇게 세션에 별도의 다른 값을 넣어 둘 수 있음 **/
        session.setAttribute("memberCode", LoginMember.getCode());
        return "redirect:/";
    }

    @PostMapping("/logout") // http 서블릿 세션 활용 로그아웃
    // 세션 종료를 위해서는 sessionManager 에 만들어두었던 expireCookie 를 사용하자
    public String loginWithHttpSession(HttpServletRequest request){

        HttpSession session = request.getSession(false);
        if(session != null){
            // invalidate 는 세션을 삭제하는 기능
            session.invalidate();
        }
        return "redirect:/";
    }

}

 


- 구동해서 직접 확인하기

요렇게 기존 세션과는 다르게 JSESSION 을 확인할 수 있습니다.

 

댓글