(인터셉터+어노테이션)로그인 체크하기(session)

2021. 10. 19. 18:22개인노트

반응형

작은 프로젝트나 개인프로젝트의 경우 보통 session에 있는 VO에 값을 저장하고 그걸로 로그인 여부를 체크한다.

그리고 특정 컨트롤러나 이런곳에서 로그인여부를 체크해야 할 경우

공통 클래스를 만들어서 그걸 필요한곳에서 호출해서 사용하는 형태로 쓰는데...그게 불편해서...

어노테이션 형태로 쓸 수는 없는가? 하고 찾아보다가 찾았다!(커스텀 어노테이션+인터셉터를 사용한 방법)

프로젝트 생성모습

1. 일단 프로젝트를 생성해준다.

기본은 롬복, devtool, web

필요한 라이브러리 가져오는 모습

2. 필요한클래스들을 생성해준다

먼저

LoginChecker 어노테이션

package com.test.sampleLogin.anno;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginChecker {
	
	//로그인체크 필수 기본값은 false, 사용할 경우 true로준다
	boolean loginCheck() default false;

}

간단한 구현을 위한 RestController

package com.test.sampleLogin.controller;

import javax.servlet.http.HttpSession;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.test.sampleLogin.VO.UsersessionVO;
import com.test.sampleLogin.anno.LoginChecker;

@RestController
public class controller {

	@GetMapping("/login")
	public String login(HttpSession session) {
		UsersessionVO usersessionVO = new UsersessionVO();
		usersessionVO.setId("id1");
		usersessionVO.setName("아무개");
		session.setAttribute("usersessionVO", usersessionVO);
		return "로그인되었습니다";
	}
	
	@GetMapping("/update")
	@LoginChecker(loginCheck = true)
	public String update() {
		return "수정되었습니다";
	}
}

보통 세션에 사용자 정보를 담을때 사용하는 사용자 정보보관용 UsersessionVO도 롬복과 함께 사용,생성해준다

package com.test.sampleLogin.VO;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class UsersessionVO {

	String id;
	String name;
}

3. 마지막으로 인터셉터를 생성한다.LoginCheckInterceptor

package com.test.sampleLogin.intercptor;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.test.sampleLogin.VO.UsersessionVO;
import com.test.sampleLogin.anno.LoginChecker;

public class LoginCheckInterceptor implements HandlerInterceptor {
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		logger.info("preHandle requestURI : {}", request.getRequestURI());
		
		if(handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			logger.info("handlerMethod : {}", handlerMethod);
			//로그인체크를 위한 커스텀 어노테이션을 가져온다
			LoginChecker methodAnnotation = handlerMethod.getMethodAnnotation(LoginChecker.class);
			//어노테이션이 존재할때
			if(methodAnnotation !=null) {
				//로그인체크가 필수라면 true값이 나와서 if문안에서 session을 확인한다.(로그인여부 확인)
				if(methodAnnotation.loginCheck()) {
					HttpSession session =request.getSession();
					UsersessionVO usersessionVO= (UsersessionVO) session.getAttribute("usersessionVO");
					if(usersessionVO!=null) {
						logger.info("usersession체크");
						logger.info(usersessionVO.toString());
					}else {
						logger.info("usersession체크");
						logger.info("로그인해야합니다! 여기서 특정프로세스 처리!");
					}
				}
			}
		}
		
		return true;
	}

}

 

그리고 해당 인터셉터를 config에 추가해줘야지 인터셉터를 적용시킨다.

package com.test.sampleLogin.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.test.sampleLogin.intercptor.LoginCheckInterceptor;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer{
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new LoginCheckInterceptor())
		.excludePathPatterns("/css/**","/fonts/**,/plugin/**,/script/**");
	}

}

##기존의경우##

아래와같은 코드가 모든 로그인이 필요한 프로세스에 들어가있다던가 or class형식으로 만들어져서 한줄이긴해도 모두 포함되어 있는경우가 많다. 

HttpSession session =request.getSession();
UsersessionVO usersessionVO= (UsersessionVO) session.getAttribute("usersessionVO");
if(usersessionVO!=null) {
  logger.info("usersession체크");
  logger.info(usersessionVO.toString());
}else {
  logger.info("usersession체크");
  logger.info("로그인해야합니다! 여기서 특정프로세스 처리!");
}

이런느낌??

	@GetMapping("/update")
	public String update(HttpSession session) {
		UsersessionVO usersessionVO= (UsersessionVO) session.getAttribute("usersessionVO");
		if(usersessionVO!=null) {
		}else {
		}
		return "수정되었습니다";
	}

##프로세스 흐름##

등록한 인터셉터에서 LoginChecker어노테이션이 존재하고 loginCheck에 적힌값이(컨트롤러 참고) true값이면 로그인이 필수라고 취급하여 session을 가져와서 UsersessionVO를 체크한다.

usersessionVO!=null 에서 로그인이 된 상태라면 usersessionVO의 값이 존재함으로 통과시키거나 원하는대로 하면되고

없는경우에는 로거에도 적혀있듯이. throws를 생성해서 던진다거나 뭐 특정메시지와 함께 로그인 폼페이지로 보내버린다거나 하면될듯 하다.

logger.info("usersession체크");
logger.info("로그인해야합니다! 여기서 특정프로세스 처리!");

 

끝!

 

 

반응형