기능구현

  • 회원가입(주소API연동, 이메일 인증, ajax를 사용하여 아이디 중복검사)
  • 관리자 페이지(인터셉터 적용, 상품관리, 회원관리)
  • 업로드(이미지 등록, 수정, 삭제)
  • 검색
  • 페이징
  • 구매(장바구니, 포인트사용)
  • 댓글(등록,수정,삭제)
  • 중간에 막혔거나 에러 해결 못하겠으면 yoonbitnara@gmail.com 으로 문의


순서

  • 로그인 메서드 적용
    • 기존 코드의 흐름
    • 새로 작성할 코드의 흐름
    • 적용
  • 테스트


로그인 메서드 적용

  • 회원가입 메서드와 같이 기존의 메서드 흐름부터 먼저 살펴보겠다.
  • 아래는 기존 코드이다.


	/* 로그인 */
	@RequestMapping(value = "login", method = RequestMethod.POST)
	public String loginPOST(HttpServletRequest request, MemberVO member, RedirectAttributes rttr) throws Exception {
		
		//System.out.println("login 메서드 진입");
		//System.out.println("전달된 데이터 : " + member);
		
		HttpSession session = request.getSession();
		MemberVO lvo = memberService.memberLogin(member);
		
		if (lvo == null) { // 아이디, 비밀번호가 일치하지 않는 경우
			int result = 0;
			rttr.addFlashAttribute("result", result);
			logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>> 로그인 실패");
			return "redirect:/member/login";
		}
		
		session.setAttribute("member", lvo); // 아이디, 비밀번호가 일치할 경우 (로그인 성공)
		
		logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>> 로그인 성공");
		
		return "redirect:/main";
	}


  • 전체적인 흐름은 다음과 같다.


memberLogin(member) 호출하여 반환받은 정보를 lvo 변수에 저장 =>(lvo==null) 작성
◇ true(lvo가 null인 경우) - 로그인 실패
=> 리플렉션에 실패를 의미하는 데이터 저장
=> 로그인 페이지 리다이렉트
◆ false(lvo가 null이 아닌 경우) - 로그인 성공
=> 세션에 사용자의 정보 저장
=> 메인 페이지로 리다이렉트


  • 여기서 가장 핵심은 memberLogin()메서드이다. 해당 메서드를 통해 select 쿼리가 실행이 되는데 사용자로부터 제출받은 아이디와 비밀번호가 일치하는 사용자를 찾게 되면 해당 사용자의 정보를 반환하게 되고 일치하는 사용자를 찾지 못하면 null을 반환하게 된다.


새로 작성할 코드의 흐름

  • 기존의 코드 경우 memberLogin() 메서드를 호출하여 쿼리문을 실행하기 위해서 사용자가 제출한 아이디, 비밀번호 데이터를 넘겨주었다. 하지만 현재 데이터베이스에 저장된 비밀번호는 인코딩 된 데이터이다. 따라서 아무리 사용자가 올바른 아이디와 비밀번호를 제출하더라도 memberLogin()메서드는 null을 반환할 것이다.


  • 데이터베이스 자체에서 인코딩된 비밀번호와 사용자가 제출한 비밀번호가 일치하는지를 판단해준다면 좋겠지만 이는 불가능하다. 그렇기 때문에 데이터베이스로부터 사용자의 비밀번호를 꺼내와서 BCryptPasswordEncoder 클래스의 matchers()메서드를 활용하여 사용자에 의해 제출된 비밀번호와 일치 여부를 확인해야 한다. 일치 여부에 따라 로그인 성공 시 실행되어야 할 코드를 적용하던지 로그인 실패 시 실행되어야 할 코드를 적용해야 할 것이다. 따라서 아래와 같은 흐름으로 코드가 진행되도록 설계하였다.


회원의 정보를 반환하는 쿼리문 실행(사용자의 아이디를 조건으로 함)
=> 회원의 정보가 null인지판단
◇ null 인경우 - 로그인 실패
=> 로그인 실패 실행 코드
◆ null 아닌 경우
=> matchers() 문을 통해 데이터베이스 저장된 비밀번호와 제출된 비밀번호 일치 여부 확인
□(true) true인 경우 - 비밀번호 일치
로그인 성공 실행 코드
■(false) false인 경우 - 비밀번호 불일치
로그인 실패 실행 코드


적용

  • 로그인 쿼리 수정
    • 새로운 쿼리를 만드는 것이 아니라 기존 작성해둔 로그인 쿼리를 활용하기 위해 일부 수정해주었다.
    • MemberMapper.xml에 있는 로그인 쿼리를 아래와 같이 수정한다.



  			<!-- select memberId, memberName, adminCk, money, point from book_member where memberId = #{memberId} and memberPw = #{memberPw} -->
  			select memberId, memberPw, memberName, adminCk, money, point from book_member where memberId = #{memberId}


  • where문에 아이디만 확인하도록 하였고 반환받는 데이터에 비밀번호도 추가하였다.


로그인 메서드 수정

  • 기존의 로그인 메서드의 구현부를 주석 처리하거나 지운다.


  • HttpSession 클래스 타입의 참조변수 session을 선언 및 초기화하고, String타입의 rawPw, encodePw변수를 선언 및 초기화 한다.
  • rawPw, encodePw는 제출받은 비밀번호와 인코딩 된 비밀번호를 잠시 저장하기 위한 용도로 사용할 것이다.


  • memberLogin() 메서드를 호출하여 위에서 수정한 쿼리가 실행이 되도록 한다. 실행된 결과로 반환받은 MemverVO 인스턴스의 주소를 MemberVO타입의 lvo 변수에 저장한다.


/* 로그인 */
	@RequestMapping(value = "login", method = RequestMethod.POST)
	public String loginPOST(HttpServletRequest request, MemberVO member, RedirectAttributes rttr) throws Exception {
		
		HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member);
	}


  • 아래와 같이 lvo가 null이냐 아니냐에 따라 코드를 분기해주는 if문을 작성한다.


HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
		}


  • if의 조건문이 false인 경우는 lvo의 저장된 값이 null이라는 의미이므로 else의 구현부는 로그인 실패 시 실행되어야 할 코드를 작성한다.


		HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
			rttr.addFlashAttribute("result", 0);
			return "redirect:/member/login";
		}


  • if(lvo != null)의 구현부는 비밀번호가 일치하는지를 확인해주는 코드를 작성해주면 된다. 먼저 rawPw와 encodePw변수에 각각 사용자가 제출한 비밀번호와 데이터베이스에 저장한 인코딩 된 비밀번호를 저장해준다.


HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			rawPw = member.getMemberPw(); // 사용자가 제출한 비밀번호
			encodePw = lvo.getMemberPw(); // 데이터베이스에 저장한 인코딩된 비밀번호
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
			rttr.addFlashAttribute("result", 0);
			return "redirect:/member/login";
		}


  • matches(인코딩 전 비밀번호, 인코딩 후 비밀번호) 메서드가 true를 반환하는지 하지 않는지를 조건문으로 하는 if문을 작성한다.


HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			rawPw = member.getMemberPw(); // 사용자가 제출한 비밀번호
			encodePw = lvo.getMemberPw(); // 데이터베이스에 저장한 인코딩된 비밀번호
			
			if (true == pwEncoder.matches(rawPw, encodePw)) { // 비밀번호 일치여부 판단
				
			} else {
				
			}
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
			rttr.addFlashAttribute("result", 0);
			return "redirect:/member/login";
		}


  • 먼저 if의 조건문이 false 경우에 실행되는 else 구현부에는 로그인 실패 시 실행되어야 할 코드를 작성한다.


HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			rawPw = member.getMemberPw(); // 사용자가 제출한 비밀번호
			encodePw = lvo.getMemberPw(); // 데이터베이스에 저장한 인코딩된 비밀번호
			
			if (true == pwEncoder.matches(rawPw, encodePw)) { // 비밀번호 일치여부 판단
				
			} else {
				
				rttr.addFlashAttribute("result", 0);
				return "redirect:/member/login";
			}
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
			rttr.addFlashAttribute("result", 0);
			return "redirect:/member/login";
		}


  • 조건문이 true인 경우 실행되는 if 구현부에는 로그인 성공 시 실행되어야 할 코드를 작성한다. session에 뷰에 보낼 사용자의 정보가 담긴 lvo를 저장하는 코드를 작성하기 전에 lvo에 저장된 사용자의 비밀번호 정보는 지워준다. 인코딩 되었더라도 굳이 노출시킬 필요는 없기 때문이다.


HttpSession session = request.getSession();
		String rawPw = "";
		String encodePw = "";
		
		MemberVO lvo = memberService.memberLogin(member); 
		
		if (lvo != null) {		// 일치하는 아이디 존재시
			
			rawPw = member.getMemberPw(); // 사용자가 제출한 비밀번호
			encodePw = lvo.getMemberPw(); // 데이터베이스에 저장한 인코딩된 비밀번호
			
			if (true == pwEncoder.matches(rawPw, encodePw)) { // 비밀번호 일치여부 판단
				
				lvo.setMemberPw("");					// 인코딩된 비밀번호 정보 지움
				session.setAttribute("member", lvo);	// session에 사용자의 정보 저장
				return "redirect:/main";				// 메인페이지 이동
				
			} else {
				
				rttr.addFlashAttribute("result", 0);
				return "redirect:/member/login";
			}
			
		}  else {				// 일치하는 아이디가 존재하지 않을 시 ( 로그인 실패 )
			
			rttr.addFlashAttribute("result", 0);
			return "redirect:/member/login";
		}


  • 이렇게 완성이 되었다.


TEST

  • 지난 포스팅에서 회원가입한 aaaaa123으로 로그인을 해본다.aaaaa123의 비밀번호는 데이터베이스에 인코딩 된 상태로 저장되어 있다.


  • 올바른 아이디 입력



  • 올바르지 않은 아이디 입력


Leave a comment