티스토리 뷰

1. 자동로그인(Remember-Me)의 처리 결과 

1 ) Login 수행시 ( LoginInterceptor )
   - 자동로그인 쿠키 생성
   - 쿠키의 유효기간(즉, 자동로그인 유효설정기간 의미) 설정
   - 응답메시지의 `Set-Cookie` 헤더에 자동로그인 쿠키 설정
   - tbl_user 테이블에 자동로그인 쿠키정보 기록

2 ) 웹브라우저를 죽이고 다시 수행시켜 접속하는 경우 ( AuthInterceptor )
   - 자동로그인 쿠키를 이용하여, Session Scope 에 인증정보(UserVO) 복원
   - 무사통과(로그인 창으로 이동시키지 않고, 요청 처리)

3 ) 명시적인 로그아웃 수행시 ( LogoutInterceptor )
   - 자동로그인쿠키(remembermeCookie) 삭제
   - tbl_user 테이블의 자동로그인쿠키컬럼(rememberme)과 rememberage 컬럼의 값을 모두 NULL로 제거


[ 1. 인터셉터 - 세션 트레킹 ] (*****)

 

[ + 이전 게시물과 이어집니다. ]

 

[ 1 - 1. Controller ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.myapp.common.SharedScopeKeys;
import org.zerock.myapp.domain.LoginDTO;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.exception.ControllerException;
import org.zerock.myapp.service.UserService;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@RequestMapping("/user/")
@Controller
public class LoginController {
	
	@Autowired
	private UserService service;
	
	// =================================================
	// + 1. 로그인 처리
	// =================================================
	
	@PostMapping("/loginPost")
	// + @ModelAttribute 어노테이션을 통해 모델에 저장할 수 있다.
	public String loginPost ( /* @ModelAttribute("loginDTO") */ LoginDTO dto, Model model, RedirectAttributes rttrs ) 
			throws ControllerException {
		
		log.trace("loginPost({}, {}) invoked.", dto, model);
		// + loginPost(LoginDTO(userid=hohohoh, userpw=1234, rememberMe=true)) invoked.
		// + view에서 post로 정보가 들어온다.
		
		try {
			
			UserVO vo = this.service.login(dto);
			log.info("\t + vo : {}", vo);
			
			if( vo != null ) { 	// 성공했을 때
				
				model.addAttribute(SharedScopeKeys.LOGIN_KEY, vo);
				
				return "user/loginPost";
				// + redirect로 할 경우에는 Request Scope이 깨지기 때문에, model안의 vo가 나오지 못한다.
				
			} else { 	// 실패했을 때
				
				rttrs.addAttribute(SharedScopeKeys.RESULT, "Login Failed.");
				return "redirect:/user/login";
				
			} // if - else
			
		} catch (Exception e) {
			throw new ControllerException(e);
		} // try - catch
		
	} // loginPost
	
	// =================================================
	// + 2. 로그 아웃 처리
	// =================================================
	// + 로그 아웃 요청시에 수행되어야 할 일 : --> LogoutInterceptor가 수행
	// + 1. Session Scope 자체를 파괴시켜야 한다. ( 즉, session.invalidate() 메소드 수행 )
	// + 2. 현재 웹 브라우저에 할당된 이름( 세션 ID )도 삭제
	// =================================================
	
	@GetMapping("/logout")
	public void logout( RedirectAttributes rttrs ) throws ControllerException {
		
		log.trace("logout() invoked.");
		// + 로그아웃은 LogoutInterceptor를 설정하기 위한 용도로만 사용될 뿐, 진짜 호출되지는 않는다.
		
	} // logout
	
	// =================================================

} // end class

 

[ 1 - 2. Interceptor ]

 

[ + 로그인 처리 인터셉터 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.interceptor;

import java.util.Date;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.zerock.myapp.common.SharedScopeKeys;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.service.UserService;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@Component
public class LoginInterceptor implements HandlerInterceptor {
	
	@Autowired
	private UserService service;
	
	// ===================================================================================================
	// + 전제 :
	// + 로그인에 성공하면 UserVO를 Session Scope에 올려 놓을 예정이다.
	// ===================================================================================================
	// + /user/loginPost로 접속 -> preHandle -> LoginController의 로그인 처리 -> postHandle
	// + preHandle에서는 이전에 접속한 
	// ===================================================================================================

	// ===================================================================================================
	// + 1. preHandle : 로그인 처리
	// ===================================================================================================
	// + Incoming Request가 Controller's Handler Method로 위임되기 직전에 가로 채는 부분
	// + Session Scope에 저장되어 있는 모든 정보를 파괴 수행
	// + (*주의*) 명시적으로 로그아웃 요청을 보내지 않는 이상, 세션 자체를 파괴해서는 안된다.
	// ===================================================================================================
	@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
		
		log.info("========================================================");
		log.trace("1. preHandle(req, res, handler) invoked.");
		log.info("========================================================");
		
		// ===================================================================
		// 1. Session Scope에 접근할 수 있는 HttpSession 객체 획득
		// ===================================================================
		HttpSession session = req.getSession();
		
		// ===================================================================
		// 2. Session Scope에 UserVO 객체가 공유 되어 있으면 삭제 처리
		// ===================================================================
		UserVO vo = (UserVO) session.getAttribute(SharedScopeKeys.USER_KEY);
		// + 현재 Session Scope에 UserVO가 있는지, 로그인 되어있는 상태인지 확인
		
		if ( vo != null ) {
			session.removeAttribute(SharedScopeKeys.USER_KEY);
			log.info("\t + Remove UserVO : {}", vo);
		} else {
			log.info("\t + No UserVO found in Session Scope");
		} // if : null이 아니라면, UserVO가 Session Scope에 올려진 상태이기에 삭제해버린다.
		
		return true;
	} // preHandle
	
	// ===================================================================================================
	// + 2. postHandle : 로그인 성공 증빙 + 자동 로그인 처리
	// ===================================================================================================

	// + 만약 컨트롤러에서 예외가 발생하면, 아래의 callback 메소드는 실행되지 않는다.
	@Override
	public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		log.info("========================================================");
		log.trace("2. postHandle(req, res, handler, {}) invoked.", modelAndView);
		log.info("========================================================");
		
		// ===================================================================
		// 1. 로그인 성공 증빙 데이터 바인딩
		// ===================================================================
		
		// + 매개변수인 modelAndView에 Model 상자 안에 UserVO 객체가 있는지 확인해 보고 ( 즉, 로그인 결과 )
		// + 만약 성공했다면, 이 UserVO 객체를 Session Scope에 있는 로그인 성공증빙으로 올려 놓기로 한다.
		
		// ===================================================================
		// 1 ) modelAndView 객체 안에 UserVO가 있는지 확인
		// ===================================================================
		ModelMap modelMap = modelAndView.getModelMap();
		UserVO vo = (UserVO) modelMap.getAttribute(SharedScopeKeys.LOGIN_KEY);
		
		// ===================================================================
		// 2 ) UserVO가 있다면( 로그인 성공 시 ) Session Scope에 UserVO를 올려 놓는다. ( 로그인 성공 증빙 )
		// ===================================================================
		if ( vo != null ) { // + 성공했을 때
			
			// + 현재 Session Scope에 접근하기 위해 HttpSession 객체 생성
			HttpSession session = req.getSession();
			
			// + Session Scope에 공유 데이터로 로그인 성공 증빙 데이터를 바인딩
			session.setAttribute(SharedScopeKeys.USER_KEY, vo);
			
			// ===================================================================
			// 2. 자동 로그인 처리
			// ===================================================================
			
			// ===================================================================
			// 1 ) 자동 로그인(rememberMe) 옵션의 on / off 여부 확인
			// ===================================================================
			boolean isRememberMeOption = checkRememberMeOption(req);
			log.info("\t + isRememberMeOption : {}", isRememberMeOption);
			
			if ( isRememberMeOption ) { // + 자동 로그인 기능 적용 유무
				
				// ===================================================================
				// 2 ) 자동 로그인 쿠키 생성
				// ===================================================================
				
				// + Response Message의 Header에 쿠키를 저장해서 보낸다.
				// + 이때 쿠키값으로는 현재 브라우저의 이름인 세션ID를 저장하자!
				// + (*주의*) 세션 ID는 UUID이다.
				
				String sessionId = session.getId();
				Cookie rememberMeCookie = new Cookie(SharedScopeKeys.REMEMBER_ME_KEY, sessionId);
				// + 쿠키는 전부 문자열이기에, 숫자로 보일지라도 문자열이다.
				// + public Cookie(String name, String value)
				
				// ===================================================================
				// 3 ) 자동 로그인 쿠키 설정
				// ===================================================================
				final int maxAge = 1 * 60 * 60 * 24 * 7;
				rememberMeCookie.setMaxAge( maxAge ); // 1주일
				// + 쿠키의 유효기간( 자동 로그인 유효기간 ) 설정
				// + .setMaxAge의 단위는 초이다.
				
				rememberMeCookie.setPath("/");
				
				// ===================================================================
				// + 쿠키 확인
				// ===================================================================
				log.info("\t + rememberMeCookie - 1. name : {}", rememberMeCookie.getName());
				log.info("\t + rememberMeCookie - 2. value : {} ", rememberMeCookie.getValue());
				log.info("\t + rememberMeCookie - 3. path : {} ", rememberMeCookie.getPath());
				log.info("\t + rememberMeCookie - 4. MaxAge : {} ", rememberMeCookie.getMaxAge());
				
				// ===================================================================
				// 4 ) 응답 메세지의 'set-cookie' 헤더에 자동설정
				// ===================================================================
				res.addCookie(rememberMeCookie);
				
				// ===================================================================
				// 5 ) tbl_user 테이블에 자동 로그인 쿠키 정보 기록
				// ===================================================================
				long currTime = System.currentTimeMillis(); 		// + 현재 시간
				long expireTime = currTime + ( maxAge * 1000 );		// + 유효기간 종료 시간
				Date date = new Date(expireTime);					// + expireTime을 Date로 변환
				
				boolean isSuccess = this.service.modifyUserWithRememberMe(vo.getUserid(), rememberMeCookie.getValue(), date );
				log.info("\t + isUpdateSuccess : {}", isSuccess);
				// + UserService.modifyUserWithRememberMe(String userid, String rememberMe, Date rememberAge);
				
			} // inner if
			
		} // if : 성공했다면

	} // postHandle
	
	// ===================================================================================================
	// + 3. afterCompletion : 주로 자원 해제하는데 사용
	// ===================================================================================================
	// + afterCompletion은 view처리가 끝난 후 User에게 응답이 나가기 직전에 인터셉트하게 되는데,
	// + 만약 처리할게 없다면, 삭제해도 된다.
	// ===================================================================================================

	@Override
	public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception e)
			throws Exception {
		
		log.info("========================================================");
		log.trace("3. afterCompletion(req, res, handler, handler, e) invoked.");
		log.info("========================================================");
		
	} // afterCompletion
	
	// ===================================================================================================
	// + 4. 자동 로그인 on / off 체크 여부 확인 메소드
	// ===================================================================================================
	
	private boolean checkRememberMeOption(HttpServletRequest req) {
		
		log.trace("checkRememberMeOption(req) invoked.");
		
		String rememberMe = req.getParameter("rememberMe");
		log.info("\t + rememberMe : {}",rememberMe);
		// + 전송 파라미터 중에서 rememberMe로 들어온 값을 변수 rememberMe에 저장
		
		return rememberMe != null;
		// + rememberMe가 null이 아니면 true를 반환하고,
		// + rememberMe가 null이라면 false를 반환한다.
		
	} // checkRememberMeOption
	
	// ===================================================================================================

} // end class

 

[ + 로그 아웃 처리 인터셉터 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.interceptor;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.WebUtils;
import org.zerock.myapp.common.SharedScopeKeys;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.service.UserService;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@Component
public class LogoutInterceptor implements HandlerInterceptor {
	
	@Autowired
	private UserService service;
	
	// ===================================================================================================
	// + 1. preHandle
	// ===================================================================================================
	
	@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
		
		log.info("========================================================");
		log.trace("1. preHandle(req, res, handler) invoked.");
		log.info("========================================================");
		
		// =======================================================================================
		// 1. 현재 브라우저에 할당된 Session Scope를 모두 파괴하고, ( 즉, 로그인 성공증빙도 파괴 )
		//    웹 브라우저에 할당된 이름( Session ID )도 무효화시킨다.
		// =======================================================================================
		
		HttpSession session = req.getSession();
		String sessionId = session.getId();
		log.info("\t + sessionID : {}", sessionId);
		
		UserVO userVO = (UserVO) session.getAttribute(SharedScopeKeys.USER_KEY);
		// + 로그아웃을 하기 위해서 로그아웃을 할 UserVO를 얻어낸다. ( 3단계에서 사용 )
		
		session.invalidate();
		log.info("\t + Current Session Scope Destroyed.");
		
		// =======================================================================================
		// 2. 로그인 성공시, 자동 로그인 옵션도 on시켜 놓은 웹 브라우저가 로그아웃을 명시적으로 수행하는 경우로 
		// 1단계도 수행되어야 하지만 자동로그인 쿠키도 삭제해줘야 한다. (***)
		// =======================================================================================
		
		Cookie rememberMeCookieToBeDestroyed = WebUtils.getCookie(req, SharedScopeKeys.REMEMBER_ME_KEY );
		// + WebUtils.getCookie(HttpServletRequest request, String name)
		// + Spring에서는 WebUtils.getCookie를 통해서 원해는 쿠키를 얻어낼 수 있다.
		
		if ( rememberMeCookieToBeDestroyed != null ) {
			
			rememberMeCookieToBeDestroyed.setMaxAge(0);
			// + 쿠키는 유효기간을 0으로 설정함으로써 즉시 파괴할 수 있다.
			
			rememberMeCookieToBeDestroyed.setPath("/");
			res.addCookie(rememberMeCookieToBeDestroyed);
			
		} // if
		
		// =======================================================================================
		// 3. 명시적으로 로그아웃 하는 것이므로, tbl_User 테이블에 있는 자동 로그인 쿠키 컬럼(rememerme)과
		// expire 일시를 기록한 rememberage 칼럼의 값을 모두 Null로 제거해 줘야 한다.
		// 그래서 명시적 로그아웃한 이후에는 더 이상 자동 로그인이 불가능하게 해야 한다. (*****)
		// =======================================================================================
		
		this.service.modifyUserWithRememberMe(userVO.getUserid(), null, null);
		// + .modifyUserWithRememberMe(String userid, String rememberMe, Date rememberAge)
		
		// =======================================================================================
		// 4. 최종적으로 로그인 화면으로 리다이렉트 수행
		// =======================================================================================
		
		req.getSession().setAttribute(SharedScopeKeys.RESULT, "Signed Out Successfully");
		// + rttrs.addAttribute(key, value)와 동일한 기능을 한다.
		
		res.sendRedirect("/user/login");
		// + 최종적으로 로그인 화면 창으로 리다이렉트 수행
		// + Redirect할 경우에는 Session Scope이 파괴된다는 것을 잊지 말아야 한다.
		// + 그렇기에, 로드인 페이지에서는 Signed Out Successfully 메시지를 얻어낼 수 없게 된다.
		
		return false;
		// + 로그아웃 요청을 컨트롤러의 핸들러로 요청을 보내지 않는다. (***)
		// + 그러나, URI는 필요하기에 컨트롤러의 메소드를 삭제하면 인터셉터도 수행이 불가능하다.
		// + 로그인 컨트롤러의 로그아웃 메소드는 단순히 형식으로만 존재하게 된다.
		
	} // preHandle

} // end class

 

[ + 인증 / 인가 인터셉터 ] 

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.interceptor;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;
import org.zerock.myapp.common.SharedScopeKeys;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.service.UserService;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@Component
public class AuthInterceptor implements HandlerInterceptor { // 인증, 인가 처리
	
	@Autowired
	private UserService service;
	
	// ===================================================================================================
	// + 1. preHandle
	// ===================================================================================================
	// + (1) 게시판에 관련된 모든 요청에 대해서 인증된 사용자(브라우저)인지를 가장 먼저 체크하고
	// + 만약, 인증되지 않은 사용자(웹 브라우저)라면, 로그인을 하도록 로그인 창으로 리다이렉트해야 한다,
	// + 위의 로직은 모든 인증 기능에서 가장 먼저 수행되어야 할 "공통 보안 로직"이다.
	// ===================================================================================================
	// + (2) 자동로그인 기능이 on되어있는 경우, 특수한 처리를 해야 된다.
	// + 	( 로그인 성공 인증 정보는 없는데, 자동 로그인 쿠키가 요청으로 날라오는 경우 )
	// ===================================================================================================
	
	@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
		
		log.info("========================================================");
		log.trace("1. preHandle(req, res, handler) invoked.");
		log.info("========================================================");
		
		// =======================================================================
		// 1. 현재 요청 URI를 전송한 사용자(웹 브라우저)의 인증여부 확인
		// =======================================================================
		
		HttpSession session = req.getSession();
		log.info("\t + 1. Session ID : {}", session.getId() );
		
		UserVO vo = (UserVO) session.getAttribute(SharedScopeKeys.USER_KEY);
		log.info("\t + 2. vo : {}", vo);
		// + Session Scope에 있는 공유 데이터 중 로그인 성공 데이터를 찾는다.
		
		if ( vo != null ) { // + 인증된 사용자(웹 브라우저)라면...
			
			log.info("\t + 3. Already Authenticated : {}", vo);
			
			return true;
			// + 요청을 컨트롤러의 헨들러로 넘긴다.
			
		} else { // + 인증되지 않은 사용자(웹 브라우저)라면...
			
			// =======================================================================
			// 2. 자동로그인 처리
			// =======================================================================
			// + 자동 로그인 처리에 필요한 처리는 2가지
			// + (1) 현재 웹 브라우저에 할당된 Session Scope에 UserVO(인증정보)를 복구해줘야 한다. (***)
			// + (2) (1) 조치를 해놓은 상태에서 무사통과시켜야 한다.
			// =======================================================================
			
			Cookie rememberMeCookie = WebUtils.getCookie(req, SharedScopeKeys.REMEMBER_ME_KEY);
			// + WebUtils.getCookie(HttpServletRequest request, String name);
			// + 자동 로그인 처리 쿠키가 존재하는지 확인한다.
			
			// =======================================================================
			// 1 ) + 자동 로그인 쿠키가 존재할 경우 (***)
			// =======================================================================
			
			if ( rememberMeCookie != null ) {
				
				String cookieName = rememberMeCookie.getName();
				String cookieValue = rememberMeCookie.getValue();
				
				log.info("\t + 4. This User has rememberMeCookie.");
				log.info( "\t + 5. rememberMeCookie found - name : {}, value : {}", cookieName, cookieValue );
				
				UserVO userVO = this.service.findUserByRememberMe(cookieValue);
				log.info("\t + 6. Found userVO : {}", userVO);
				// + 이를 통해서 쿠키의 값을 통해서, userVO객체를 얻어낸다.
				
				session.setAttribute(SharedScopeKeys.USER_KEY, userVO);
				// + findUserByRememberMe를 통해 UserVO객체를 받아와 로그인 성공증빙과 같이 만든다.
				
				return true;
				// + 쿠키가 있을 경우 로그인 성공 인증정보가 없어도 무사히 통과할 수 있도록
				// + 요청을 컨트롤러의 헨들러로 넘긴다.
				
			} // if : 자동 로그인 처리 수행 -> 무사통과
			
			// =======================================================================
			// 2 ) + 자동 로그인 쿠키가 존재하지 않을 경우
			// =======================================================================
			
			log.info("\t + NO Authenticated User");
			
			res.sendRedirect("/user/login");
			// + 로그인 창으로 리다이렉트해버린다.
			
			return false;
			// + 요청을 컨트롤러의 헨들러로 넘기지 않는다.
			// + 인증되지 않은 사용자의 경우에는 게시물로 접근이 불가능해야 한다.
			
		} // if - else
		
	} // preHandle
	
	// ===================================================================================================
	// + 2. postHandle
	// ===================================================================================================

	// + 만약 컨트롤러에서 예외가 발생하면, 아래의 callback 메소드는 실행되지 않는다.
	@Override
	public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		log.info("========================================================");
		log.trace("2. postHandle(req, res, handler, {}) invoked.", modelAndView);
		log.info("========================================================");

	} // postHandle
	
	// ===================================================================================================
	// + 3. afterCompletion
	// ===================================================================================================

	@Override
	public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception e)
			throws Exception {
		
		log.info("========================================================");
		log.trace("3. afterCompletion(req, res, handler, handler, e) invoked.");
		log.info("========================================================");
		
	} // afterCompletion
	
} // end class

 

[ 1 - 3. Mapper에 sql문 추가 ]

 

더보기

[ + 코드 보기 ]

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zerock.myapp.persistence.UserDAO">

    <select 
        id="selectUser" 
        resultType="org.zerock.myapp.domain.UserVO">

        <![CDATA[ 
            SELECT * 
            FROM tbl_user 
            WHERE userid = #{userid} AND userpw = #{userpw} 
        ]]>

    </select>

    <!-- ========================================================================================= -->

    <select 
        id="selectUserByRememberMe" 
        resultType="org.zerock.myapp.domain.UserVO">
    
        SELECT userid, userpw, uname, upoint
        FROM tbl_user
        WHERE rememberme = #{rememberMe} AND rememberage >= current_date
        <!-- rememberage는 유효기간으로, 현재날짜보다 유효기간이 커야지 유효하다. -->
    
    </select>
    
    <!-- ========================================================================================= -->

    <update id="updateUserWithRememberMe">

        UPDATE tbl_user
        SET
            rememberme = #{rememberMe, jdbcType=VARCHAR},
            rememberage = #{rememberAge, jdbcType=DATE}
        WHERE
            userid = #{userid}
        
    </update>

</mapper>

 

[ 1 - 4. DAO 추가 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.persistence;

import java.util.Date;

import org.zerock.myapp.domain.LoginDTO;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.exception.DAOException;

public interface UserDAO {
	
	// 1. 로그인 창에서 입력한 아이디와 암호에 매칭되는 사용자의 정보 획득
	public abstract UserVO selectUser(LoginDTO dto) throws DAOException;
	
	// 2. 자동 로그인 설정이 on된 상태로 로그인 성공시, 쿠키 정보를 기록
	public abstract int updateUserWithRememberMe( String userid, String rememberMe, Date rememberAge ) throws DAOException;

	// 3. 자동 로그인 쿠키값으로 사용자를 조회하여 인증정보를 생성
	public abstract UserVO selectUserByRememberMe(String rememberMe) throws DAOException;
	
} // end interface

 

[ 1 - 5. DAO 구현 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.persistence;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.zerock.myapp.domain.LoginDTO;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.exception.DAOException;

import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@NoArgsConstructor

@Repository
public class UserDAOImpl implements UserDAO {

	@Autowired
	private SqlSessionFactory sqlSessionFactory;
	
	@Override
	public UserVO selectUser(LoginDTO dto) throws DAOException {
		
		log.trace("selectUser({}) invoked.", dto);
		
		SqlSession sqlSession = this.sqlSessionFactory.openSession();
		
		try ( sqlSession ){
			
			String namespace = "org.zerock.myapp.persistence.UserDAO";
			String sqlId = "selectUser";
			String sql = namespace + "." + sqlId;
			
			return sqlSession.<UserVO>selectOne(sql, dto);
			
		} catch(Exception e) {
			throw new DAOException(e);
		} // try - with - resources
		
	} // selectUser

	@Override
	public int updateUserWithRememberMe(String userid, String rememberMe, Date rememberAge) throws DAOException {
		
		log.trace("updateUserWithRememberMe({}, {}, {}) invoked.", userid, rememberMe, rememberAge );
		
		SqlSession sqlSession = this.sqlSessionFactory.openSession();
		
		try ( sqlSession ){
			
			String namespace = "org.zerock.myapp.persistence.UserDAO";
			String sqlId = "updateUserWithRememberMe";
			String sql = namespace + "." + sqlId;
			
			Map<String, Object> params = new HashMap<>();
			params.put("userid", userid);
			params.put("rememberMe", rememberMe);
			params.put("rememberAge", rememberAge);
			
			return sqlSession.update(sql, params);
			
		} catch(Exception e) {
			throw new DAOException(e);
		} // try - with - resources
		
	} // updateUserWithRememberMe

	@Override
	public UserVO selectUserByRememberMe(String rememberMe) throws DAOException {
		
		log.trace("selectUserByRememberMe({}) invoked.", rememberMe);
		
		SqlSession sqlSession = this.sqlSessionFactory.openSession();
		
		try ( sqlSession ){
			
			String namespace = "org.zerock.myapp.persistence.UserDAO";
			String sqlId = "selectUserByRememberMe";
			String sql = namespace + "." + sqlId;
			
			return sqlSession.<UserVO>selectOne(sql, rememberMe);
			
		} catch(Exception e) {
			throw new DAOException(e);
		} // try - with - resources
		
	} // selectUserByRememberMe

} // end class

 

[ 1 - 6. Service 추가 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.service;

import java.util.Date;

import org.zerock.myapp.domain.LoginDTO;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.exception.DAOException;
import org.zerock.myapp.exception.ServiceException;

public interface UserService {

	// =====================================================================
	// 1. 로그인 창에서 입력한 아이디와 암호에 매칭되는 회원이 있는지 확인
	// =====================================================================
	// ReturnType을 Boolean이 아닌 UserVO로 하는 이유는,
	// 이 객체를 바로 로그인 성공 정보로 Session Scope에 바인딩시키기 위해서이다.
	public abstract UserVO login(LoginDTO dto) throws ServiceException;
	
	// =====================================================================
	// 2. 자동 로그인 설정이 on된 상태로 로그인 성공시, 쿠키 정보를 기록
	// =====================================================================
	public abstract boolean modifyUserWithRememberMe( String userid, String rememberMe, Date rememberAge ) throws ServiceException;

	// =====================================================================
	// 3. 자동 로그인 쿠키값으로 사용자를 조회하여 인증정보를 생성
	// =====================================================================
	public abstract UserVO findUserByRememberMe(String rememberMe) throws ServiceException;
	
} // end interface

 

[ 1 - 7. Service 구현 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.service;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zerock.myapp.domain.LoginDTO;
import org.zerock.myapp.domain.UserVO;
import org.zerock.myapp.exception.DAOException;
import org.zerock.myapp.exception.ServiceException;
import org.zerock.myapp.persistence.UserDAO;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;


@Log4j2
@AllArgsConstructor

@Service
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserDAO userDAO;

	// ===============================================================
	// + 1. 로그인 처리
	// ===============================================================
	
	@Override
	public UserVO login(LoginDTO dto) throws ServiceException {
		
		log.trace("login({}) invoked.", dto);
		
		try {
			return this.userDAO.selectUser(dto);
		} catch ( DAOException e ) {
			throw new ServiceException(e);
		} // try - catch
		
	} // login
	
	// ===============================================================

	@Override
	public boolean modifyUserWithRememberMe(String userid, String rememberMe, Date rememberAge) throws ServiceException {
		
		log.trace("modifyUserWithRememberMe({}, {}, {}) invoked.", userid, rememberMe, rememberAge);
		
		try {
			return this.userDAO.updateUserWithRememberMe(userid, rememberMe, rememberAge) == 1;
		} catch ( DAOException e ) {
			throw new ServiceException(e);
		} // try - catch
		
	} // modifyUserWithRememberMe
	
	// ===============================================================

	@Override
	public UserVO findUserByRememberMe(String rememberMe) throws ServiceException {
		
		log.trace("findUserByRememberMe({}) invoked.", rememberMe);
		
		try {
			return this.userDAO.selectUserByRememberMe(rememberMe);
		} catch ( DAOException e ) {
			throw new ServiceException(e);
		} // try - catch
		
	} // findUserByRememberMe
	
	// ===============================================================

} // end class
728x90
댓글
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항