Interceptor & Auto Login

Let's Just Go·2022년 7월 25일
0

Spring

목록 보기
14/26

Spring

Interceptor

  • Intercepter

    • Controller 직전에 위치하여 특정 요청에 대해서 한번 걸러주는 역할로 Controller 전 후로 요청을 처리

    • Controller 실행 전 후로 Controller 입력 및 출력을 제어

    • Interface에 HandlerInterceptorAdapter 클래스를 상속받아서 사용

    • servlet-context.xml에 태그 추가하여 사용 가능(bean 등록을 하기 위해)

    • PreHandler의 경우 return을 통해 controller의 실행 여부 결정 가능

    • PostHandler의 경우 매개변수로 전달되는 ModelAndView를 통해 Controller에서 저장한 model 데이터를 컨트롤 가능

      package com.spring.mvc.board.commons.interceptor;
      
      import java.io.PrintWriter;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      
      import org.springframework.web.servlet.HandlerInterceptor;
      import org.springframework.web.servlet.ModelAndView;
      
      // interceptor class를 만들려면 HandlerInterceptor 인터페이스를 구현 
      public class BoardInterceptor implements HandlerInterceptor{
      	
      	
      	// preHandle은 컨트롤러로 들어가기 전 처리해야 할 로직을 작성
      	@Override
      	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      			throws Exception {
      		
      		System.out.println("게시판 인터셉터 발동 확인 : preHandle");
      		// 해당 메소드는 override라서 매개변수를 바꾸거나 return 타입을 바꾸면 안됨
      		HttpSession session = request.getSession();
      		// HttpServletRequest 객체가 매개변수로 있으므로 getsession()으로 session가져올 수 있음 
      		
      		if (session.getAttribute("login") == null) {
      			
      			System.out.println("회원 인증 실패 ");
      			
      			response.setContentType("text/html; charset=UTF-8");
      			PrintWriter out = response.getWriter();
      			
      			String htmlcode = "<script> \r\n"
      					+ "alert('로그인이 필요한 페이지입니다.'); \r\n"
      					+ "location.href='/'"
      					+ "</script>";
      			// 로그인을 하지 않으면 메인 페이지로 이동 
      			
      			out.print(htmlcode);
      			out.flush();
      			return false;
      			// return을 false로 주면 controller로 요청이 전달되지 않음
      		}
      		System.out.println("회원 인증 성공 ");
      		return true;
      		// return을 true로 리턴하면 아무일도 일어나지 않고 요청이 전달
      	}
      	
      	// postHandle은 컨트롤러를 나갈 때 공통 처리해야 할 내용을 작성 
      	@Override
      	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      			ModelAndView modelAndView) throws Exception {
      		// ModelAndView가 있으므로 Controller에서 저장한 model의 값을 볼 수 있음 
      		
      		System.out.println("게시판 인터셉터 발동 확인 : postHandle");
      		
      		System.out.println("모델 객체 내부 : " + modelAndView.getModel());
      		Object data = modelAndView.getModel().get("article");
      		System.out.println("article 이라는 이름의 데이터 : " + data);
      		System.out.println("뷰 페이지 이름 : " + modelAndView.getViewName());
      		
      		// 컨트롤러에서 로직을 처리하고 나가는 흐름을 붙잡아서 모델 데이터가 제대로 전송되는지 확인하고 
      		// 추가할 내용이나 수정할 내용이 있다면 모델 객체를 받아와서 추가, 수정 가능 
      		// 기타 특징을 활용해서 흐름을 제어할 수 있음 (sendRedirect, viewName 수정을 통해)
      	}
      }

Auto Login

  • 자동 로그인은 Session과 Cookie를 활용하여 Auto Login 기능 수행 가능

    • autoLogin을 클릭하면 sessionid와 expired date를 db 컬럼으로 저장

    • 사용자가 다시 접속했을 때 sessionid를 통해서 연산 진행 후 만약 같다면 자동 로그인 진행

    • 비동기 방식으로 진행

      // 로그인 요청 처리 
      	@PostMapping("/loginCheck")
      	public String loginCheck(@RequestBody UserVO user, /* 1번 방법 HttpServletRequest request*/
      			HttpSession session, HttpServletResponse response) {
      		System.out.println("/user/loginCheck : POST");
      		// 서버에서 세션 객체를 얻는 방법
      		// 1. HttpServletRequest 객체 사용 (메서드의 매개변수로 넣어줌)
      //		HttpSession session = request.getSession();
      		
      		// 2. 매개값으로 HttpSession 객체 받아서 사용 특정 메서드에 sesion정보 입력
      			// 오버라이딩을 할 경우 매개변수를 마음대로 바꾸지 못해서 2번은 문제가 발생할 수 있음
      
      		UserVO dbData = service.selectOne(user.getAccount());
      		
      		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
      		// 암호화된 비밀번호를 가져오기 위해
      		
      		if (dbData != null) {
      			if (encoder.matches(user.getPassword(), dbData.getPassword())) {
      				// 사용자가 입력한 비밀번호를 암호화 했을 때 기존에 저장된 암호화된 비밀번호가 같은지
      				
      				// 로그인을 성공했다면 로그인 성공 대상으로 세션 정보 생성 
      				session.setAttribute("login", dbData);
      				
      				long limitTime = 60*60*24;
      				// 자동로그인 유효 기간 
      				
      				// 로그인을 성공했고 자동 로그인 체크 시 처리해야 할 내용
      				if (user.isAutoLogin()) {
      					// 자동 로그인을 체크했다면 
      					// 자동 로그인 희망하는 경우 쿠키를 이용하여 자동 로그인 정볼르 저장 
      					System.out.println("자동 로그인 쿠키 생성 중 ...");
      					// 세션 아이디를 가지고 와서 쿠키에 저장(고유한 값이 필요함)
      					
      					// 쿠키 생성 
      					Cookie loginCookie = new Cookie("loginCookie", session.getId());
      					// 이름이 loginCookie이고 값이 sessionID인 쿠키 생성 
      					
      					loginCookie.setPath("/");
      					// 쿠키가 동작할 수 있는 유효한 url 설정
      					
      					loginCookie.setMaxAge((int) limitTime);
      					// 쿠키가 유효할 수 있는 기간 
      					
      					response.addCookie(loginCookie);
      					// 쿠키 추가 
      					
      					// 자동 로그인 유지 시간을 날짜 객체로 변환 
      					// DB에 삽입하기 위해서 (밀리초)
      					long expiredDate = System.currentTimeMillis() + (limitTime * 1000);
      					Date limitDate = new Date(expiredDate);
      					// Date 객체의 생성자에 매개값으로 밀리초의 정수를 전달해주면 날짜 형태로 변경해줌
      					System.out.println("자동 로그인 만료 시간 : " + limitDate);
      					
      					System.out.println("session id : " + session.getId());
      					service.keepLogin(session.getId(), limitDate, user.getAccount());
      				}
      				return "loginSuccess";
      			} else {
      				return "pwFail";
      			}
      		} else {
      			return "idFail";
      		}
      	}

Logout

  • 로그아웃은 로그인으로 생성된 Session을 삭제하기만 하면 됨

    • 자동 로그인 유저 로그아웃

    • 자동 로그인을 유지하기 위해 생성한 Cookie는 request객체 안에 존재함으로 HttpServletRequest를 매개변수로 추가

    • 생성한 Cookie를 삭제하고 로그인 유지를 하기 위해 DB에 저장한 값을 바꿔줌

      // 로그아웃 처리
      	@GetMapping("/logout")
      	public ModelAndView logout(HttpServletRequest request, HttpServletResponse response, HttpSession session, RedirectAttributes ra
      			/*HttpServletResponse response*/) throws IOException {
      		System.out.println("/user/logout : GET");
      
      		// 자동 로그인 설정을 한 사용자는 쿠키를 삭제해야 완전히 로그아웃 됨 
      		Cookie loginCookie = WebUtils.getCookie(request, "loginCookie");
      		// 쿠키는 request 객체 안에 존재함으로 매개변수로 request객체를 가져옴
      		// 쿠키의 이름이 loginCookie라는 쿠키를 쉽게 가져옴 
      		String sessionId = "none";
      		
      		// db에 저장된 session정보 바꿔야함 
      		// 세션아이디, 만료시간
      		long changeExpiredDate = System.currentTimeMillis();
      		// 현재시간 
      		Date chLimitDate = new Date(changeExpiredDate);
      		// 밀리초로 되어 있는 것을 날짜로 바꿔줌 
      		UserVO user = (UserVO) session.getAttribute("login");
      		// user의 account가 필요함으로 session에서 정보를 받아옴 
      		
      		if (loginCookie != null) {
      			// 만약 사용자가 자동 로그인을 설정했을 때 쿠키가 존재한다면 
      			loginCookie.setMaxAge(0);
      			// 쿠키의 수명을 0으로 바꿔 소멸 
      			loginCookie.setPath("/");
      			// 쿠키 소멸 끝 
      			response.addCookie(loginCookie);
      			
      			service.keepLogin(sessionId, chLimitDate, user.getAccount());
      		}
      		
      		session.invalidate();
      		// 세션 삭제
      		
      		
      		ra.addFlashAttribute("msg", "logout");
      		// 요청을 보낸 header.jsp에 msg 보냄
      		
      //		return "redirect:/";
      		// 비동기 전송이라서 그냥 보내면 화면에 return한 데이터가 뜸
      //		response.sendRedirect("/");
      //		// sendRedirect로도 보낼 수 있음 
      		
      		// ModelAndView를 사용하게 되면 어디로 보낼 지 지정할 수 있음 
      		ModelAndView mv = new ModelAndView();
      		mv.setViewName("redirect:/");
      		// 로그아웃 되었으니 홈화면으로 다시 요청해서 전달 
      		return mv;
      	}
profile
안녕하세요! 공부한 내용을 기록하는 공간입니다.

0개의 댓글