요르딩딩

Spring - Interceptor 본문

[Web]/[Spring]

Spring - Interceptor

요르딩딩 2022. 11. 11. 17:31
728x90
반응형

이번시간에는 intercept를 활용한 Session체크 공통부분을 구현해 보았습니다.

인증 확인은 크게 Filter와 Interceptor를 활용하여, controller에 접근하기 전에 전처리할 수 있도록 공통화를 많이 한다고 합니다.

 

저희 회사는 세션관련 객체를 controller 또는 service단에서 처리를 하고 있었습니다. 그 이유는 회사 방침이 그렇게 적용되고 있었기 때문입니다. 그런데 이렇게 하니 모든 API를 만들때마다 꽤나 긴 공통코드를 여러번 반복해야하고, Controller 또는 Service단까지 들어와야 인증체크를 할 수 있기에 그다지 좋은 방식은 아니라고 생각합니다.

 

그리하여, filter와 interceptor에서 공통으로 전처리를 하면 좋을거 같다는 생각을 했습니다.

처음에는 filter가 더 앞단으로, filter에 적용하려하였으나, 회사 프레임워크를 사용해야하는 이슈가 있었습니다.

회사 프레임워크를 사용하지 않고, 개발할시 여러가지 이슈가 발생할 수 있고, 회사내부 세션체크 정책이 바뀌면 일일히 바꿔줘야하는 이슈가 있어, 최대한 회사 프레임워크를 사용하는 방향으로 개발하기로 했습니다. 

(filter는 dispatcher-servlet의 앞단에서 실행하기 때문에, 스프링영역 밖이라 컨테이너에 등록된 빈을 사용할 수 없는 이슈가 발생)

 

그러므로, dispatcher-servlet 다음의 Spring영영에 위치한 interceptor를 사용했습니다.

interceptor는 Spring영역으로 빈으로 등록된 객체를 사용할 수 있기에 보다 적합하다고 생각했기 때문입니다.

 

(실행순서 : Client > Filter > Dispatcher-servlet > Interceptor > Controller > Service > ~~~)

 

 

[Session 클래스] 

세션객체를 담을 클래스 선언

package com.~~.dto;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Session {
	
	private long userNo;
	private long companyNo;
	private String portalId;
	private String userName;	
}

 

[interceptor 구현부]

회사내부 설정대로 세션을 체크한뒤, 새로운 세션객체에 담아서 controller단으로 전달했습니다.

새로운 객체를 사용하는 이유는 프레임워크에 있는 객체는 불필요 정보까지 담겨있기에 필요한 것만 따로 저장하여 전달했습니다.

package com.~~.interceptor;

import java.util.Properties;

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.DUZEX.common.model.RuSession;
import com.DUZEX.Ru.common.service.SessionService;
import com.DUZEX.Ru.~~.dto.Session;

public class sessionInterceptor extends HandlerInterceptorAdapter {

	protected Logger logger = LogManager.getLogger(this.getClass());
	
	@SuppressWarnings("unused")
	private final Properties RuProperties;
	private final SessionService sessionService;

	@Autowired
	sessionInterceptor(Properties RuProperties, SessionService sessionService) {
		this.RuProperties = RuProperties;
		this.sessionService = sessionService;
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		System.out.println("===================       START       ===================");
		System.out.println(" Request URI \t:  " + request.getRequestURI());
		
        // 내부 세션 체크 정책
		RuSession RuSession = sessionService.getSession();
		if (RuSession == null || RuSession.getUser_no() == null || RuSession.getCompany_no() == null) {
			System.out.println("===================    No Session     ===================");
			return false;
		}
		
		Session session = new Session();
		session.setUserNo(RuSession.getUser_no());
		session.setCompanyNo(RuSession.getCompany_no());
		session.setPortalId(RuSession.getPortal_id());
		session.setUserName(RuSession.getUser_name());
		
		// DUZEX은 RequestUtil.paramToHashMap에서 주소값을 그냥 스트링으로 바꿔버림...
		request.setAttribute("session", session);  
		
		return super.preHandle(request, response, handler);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {

		System.out.println("===================        END        ===================\n");

		super.postHandle(request, response, handler, modelAndView);
	}
}

 

[interceptor 설정 - context-interceptor.xml]

모든 경로로 들어온거 적용

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">


	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**" />
			<bean class="com.~~.interceptor.sessionInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

</beans>

web.xml 의 아래 부분이 context-interceptor.xml을 읽습니다.

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath*:spring/context-*.xml</param-value>
</context-param>

 

[controller]

interceptor에서 받아온 객체를 param에 넣어 service단으로 넘깁니다.

( -> 기존의 방식을 최대한 고수하기 위해 사용)

	/**
	 * 예시 Controller
	 */
	@GetMapping("test/test1")
	public Entity<?> select(HttpServletRequest request) throws Exception {
		//모두 String으로 변환, Session의 경우 주소가 String으로 변환되는 이슈
		HashMap<String, Object> param = RequestUtil.paramToHashMap(request);
		
		// 세션객체 service단으로 넘기기
		Session session = (Session) request.getAttribute("session");
		param.put("session",session);
		
		RuResult result = service.selectInfo(param);
		return ResponseUtil.response(result);
	}

 

[Service]

//호츌
Session session = (Session) param.get("session");

//사용
System.out.println(session);
System.out.println(session.getUserNo());
System.out.println(session.getCompanyNo());

 

728x90
반응형

'[Web] > [Spring]' 카테고리의 다른 글

@ExceptionHandler, @Valid  (0) 2022.12.27
Spring - Filter  (0) 2022.11.11
[Spring] branch 생성 및 적용하는법  (0) 2022.09.20
JUnit 테스트하는 방법  (0) 2022.09.14
DTO를 사용해보자  (0) 2022.08.12
Comments