[Spring] 로그인 기능 구현 (1) - 쿠키, 세션

dooboocookie·2022년 10월 8일
2

요구사항


1. 회원 엔티티에 있는 데이터를 통하여 이메일, 비밀번호가 일치하는 회원이 로그인 요청 시 인증처리
2. 로그인 여부, 회원 등급에 따라 접근 권한 인가처리

인증(Authentication)

  • 로그인 처리
  • 접근하는 것이 누구인지 판단하고 확인하는 절차
  • 방법
    1. 세션, 쿠키를 이용
    2. JWT(Access Token) 이용
    3. OAuth 이용
    4. SNS 인증

로그인 처리

  1. MemberRepository.java
public List<Member> findByLoginMail(String loginMail) {
	// 로그인 시도하는 이메일과 일치하는 회원정보를 가져오는 JPQL
    // .getSingleResult는 없을 시, 예외를 뱉기 때문에 리스트로 받아옴
 	return em.createQuery("select m from Member m where m.memMail =:memMail", Member.class)
                .setParameter("memMail", memMail)
                .getResultList();
}
  1. MemberController.java
@PostMapping("/login")
public String login(
	@ModelAttribute LoginForm form,
    HttpServletRequest request,
    HttpServletResponse response
) {
	List<Member> loginMemeber = memberRepsitory.findByLoginMail(form.getMail());
    
    if(!loginMember.isEmpty()) {
    	Member member = loginMember,get(0);
        //중복된 이메일이 없을 것이라는 가정하에 이렇게 진행
    } else { 
    	log.info("이메일 맞지 않음");
        return "loginForm";
    }
    
   	if(member.getPassword().equals(form.getPassword())) {
    	log.info("로그인 성공!!");
    	return "redirect:/";
    } else { 
    	log.info("비밀번호 맞지 않음");
        return "loginForm";
    }
}

인가(Authorization)

  • 접근하려는 클라이언트의 로그인 여부, ROLE 등을 판단하여 접근 권한을 판단하는 절차

  • 위에서 로그인 인증이 성공한 클라이언트는 회원으로 접근이 가능한 페이지는 접근 가능하도록 해야한다.

쿠키(Cookie) 사용

  1. /login요청으로 회원임을 확인 하고 로그인 인증이 완료된 클라이언트에겐 쿠키를 발급
  2. 그 이후에 다른 요청을 할 때 그 쿠키를 읽어 서버에서 읽어 해당 사용자임을 판단

쿠키 생성

  • MemberController.java
	if(member.getPassword().equals(form.getPassword())) {
    	log.info("로그인 성공!!");
        Cookie loginCookie = new Cookie("loginMail", member.getMail());
        response.addCookie(loginCookie);
    	return "redirect:/";
    }
  • → 로그인 성공 시, HTTP 응답에 loginMail:bkh3030@gmail.com과 같은 형태로 쿠키를 담아 보냄

인가 처리

@GetMapping("/인가처리가 필요한 요청 URL")
public String auth(
	@CookieValue(name = "loginMail", required = false) String loginMail,
    Model model
){
	if(loginMail == null) {
    	//로그인이 필요함
        return "redirect:/login";
    }
    
    Member member = memberRespository.findByMail(loginMail);
    model.addAttribute("member", member);
    //로그인된 회원 정보를 가지고 뷰페이지로 보냄
    return "포워딩시킬 뷰페이지";
}

로그아웃(쿠키)

  • 로그아웃 요청 시, 해당 이름의 쿠키의 종료날짜를 0(혹은 그 이하)로 하고 응답을 보냄
Cookie cookie = new Cookie("loginMail", null);
cookie.setMaxAge(0);
response.addCookie(cookie);

쿠키만 사용했을 때의 치명적인 문제

  1. 쿠키 값은 클라이언트에 저장되는 정보기 때문에 클라이언트가 임의적으로 내용을 변경할 수 있음
  2. 쿠키에 저장되는 값이 매우 중요한 정보일 확률이 크기 때문에 보안에 매우 취약함

세션(Session)

  • 서블릿에서 제공하는 HttpSession을 사용하여 로그인한 회원 정보는 서버에 저장한다.
    • 서버에는 JSESSIONID라는 쿠키 이름으로 유니크한 랜덤 값이 저장된다.
    • 해당 쿠키 값으로 어떤 클라이언트의 세션인지 파악할 수 있음

세션 생성

	if(member.getPassword().equals(form.getPassword())) {
    	log.info("로그인 성공!!");
        HttpSession session = request.getSession(true);
        session.setAttribuet("loginMember", member);
    	return "redirect:/";
    }
  • reqeust.getSession()의 파라미터
    • true는 세션이 없으면 새로운 세션을 만든다.
    • flase는 세션이 없으면 세션을 만들지 않는다. (null)
    • 기본값은 true

인가 처리

@GetMapping("/인가처리가 필요한 요청 URL")
public String auth(
	HttpServletRequest request,
    Model model
){
	//세션이 없을 시(로그인이 안됐을 때),  새로운 세션 만들지 않음
    //이 과정은 로그인 인증처리를 하는 과정이 아니라
    //로그인이 되어있는 지 확인하는 과정이기 떄문
   	HttpSession session = request.getSession(false);
   	if (session == null) {
    	//로그인이 필요함
   		return "redirect:/login";
   	}
   	Member loginMember = (Member)session.getAttribute("loginMember");
	if(loginMember == null) {
    	//로그인이 필요함
        return "redirect:/login";
    }
    
    model.addAttribute("member", loginMember);
    //로그인된 회원 정보를 가지고 뷰페이지로 보냄
    return "포워딩시킬 뷰페이지";
}
  • 매개변수로 @SessionAttribute로 받아와도 됨
  • 혹은 새로운 어노테이션과 아규먼트 리졸버를 설정해도 됨

로그아웃

session.invalidate();
  • 세션을 제거하여, 로그인 정보를 지움

주의

  1. 세션은 N명의 사용자가 접속해서 로그인 처리를하면, N개의 데이터가 서버에 저장되기 때문에 적절한 데이터를 받아야 한다.
  2. 사용자가 로그아웃하지 않고, 종료를 하면 서버에서는 자동으로 세션을 지우지 않기 때문에 세션 종료 시점을 설정해줘야 한다.
  3. 세션 종료 시점은 LastAccessedTime속성의 시간 이후, 즉 사용자가 세션으로 접근한 마지막 시간으로 부터 얼마나 지났는지를 체크하고 세션을 삭제하는 것이 제일 적절

김영한 선생님 - [스프링 MVC 2편 - 백엔드 웹 개발 활용 기술] (인프런 강의) 참조

profile
1일 1산책 1커밋

0개의 댓글