상세 컨텐츠

본문 제목

[Spring/Filter] Filter에 허용한 Ip 이외에는 차단하기.

Development/Spring

by J-Developer 2022. 5. 31. 16:54

본문

반응형

클라우드를 사용하면 로드밸런스 단에서 처리하면 되지만 이 소스는 약 3년전에 진행한 프로젝트에서 처리한 것으로

그냥 호스팅 서버를 사용하고 있어 애플리케이션 단에서 Ip 차단을 하는 것을 만들었다.

간단하게 Filter에서 처리는 코드이다.

Spring은 전자정부프레임워크이다.

 

 

- web.xml

	<filter>
		<filter-name>ipServletFilter</filter-name>
		<filter-class>gstartupAdmin.common.filter.IpServletFilter</filter-class>
  	</filter>
  	
  	<filter-mapping>
  		<filter-name>ipServletFilter</filter-name>
  		<url-pattern>*</url-pattern>
  	</filter-mapping>

 

- ApplicationContext-servlet.xml

<bean id="ipServletFilter" class="gstartupAdmin.common.filter.IpServletFilter"/>

 

- IpServletFilter.java

package gstartupAdmin.common.filter;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class IpServletFilter implements Filter {

	private final String SYS_PROPERTIES_LOCATION = "/config/sys.properties";
	private final String[] LOCAL_IP_ARR = {"127.0.0.1", "0:0:0:0:0:0:0:1"};
	private String accessIpStr;
	
	@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="잘못된 접근입니다.")
    public class NotAccessException extends RuntimeException {}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}

	@Override
	public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {
		
		String userIp = "";

		if( request instanceof HttpServletRequest ) {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			userIp = getClientIpAddr( httpRequest );
		}
		else {
			userIp = request.getRemoteAddr();
		}
		
		System.out.println( "===========================================================================================================" );
		System.out.println( "접속 IP :::: " + userIp );
		System.out.println( "===========================================================================================================" );
		
		boolean isAccess = false;
		
		for( String ip : LOCAL_IP_ARR ) {
			if( ip.equals( userIp ) ) {
				isAccess = true;
				break;
			}
		}
		
		if( isAccess ) {
			chain.doFilter( request, response );
			return;
		}
		
		if( StringUtils.hasText( accessIpStr ) ) {
			
			String[] accessIpArr = accessIpStr.split( "," );

			try {
				for( String ip : accessIpArr ) {
					
					if( ip.indexOf( "/" ) >= 0 ) {
						isAccess = checkIpBand( ip, userIp );
					}
					else if( ip.indexOf( "*" ) >= 0 ) {
						isAccess = checkIpAll( ip, userIp );
					}
					else {
						
						if( ip.equals( userIp ) ) {
							isAccess = true;
						}
						
					}
					
					if( isAccess ) {
						break;
					}
					
				}
			}
			catch ( Exception e ) {
				e.printStackTrace();
				isAccess = false;
			}
			
		}
		
		if( isAccess ) {
			chain.doFilter( request, response );
			return;
		}

		//throw new NotAccessException();
		
	}

	@Override
	public void init( FilterConfig filterConfig ) throws ServletException {
		Properties applicationProperties = new Properties();
		InputStream is = WebApplicationContextUtils.class.getResourceAsStream( SYS_PROPERTIES_LOCATION );
		try {
			InputStreamReader isr = new InputStreamReader(is, "UTF-8");
			applicationProperties.load( isr );
			accessIpStr = applicationProperties.getProperty( "accessIp" );
		}
		catch ( UnsupportedEncodingException e ) {
			e.printStackTrace();
		}
		catch ( IOException e ) {
			e.printStackTrace();
		}
	}
	
	/**
	 * IP를 조금 더 정확하게 가져옵니다.
	 * @param request
	 * @return
	 */
	private String getClientIpAddr( HttpServletRequest request ) {
		
		if ( request == null ) {
			return "";
		}
		
		String ip = request.getHeader( "X-Forwarded-For" );

		if ( ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase( ip ) ) {
			ip = request.getHeader( "Proxy-Client-IP" );
		}
		if ( ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase( ip ) ) {
			ip = request.getHeader( "WL-Proxy-Client-IP" );
		}
		if ( ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase( ip ) ) {
			ip = request.getHeader( "HTTP_CLIENT_IP" );
		}
		if ( ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase( ip ) ) {
			ip = request.getHeader( "HTTP_X_FORWARDED_FOR" );
		}
		if ( ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase( ip ) ) {
			ip = request.getRemoteAddr();
		}

		return ip;
		
	}
	
	private boolean checkIpBand( String ip, String userIp ) throws Exception {
		
		boolean result = true;
		String[] ipArr = ip.split( "\\." );
		String[] userIpArr = userIp.split( "\\." );
		
		for( int i = 0; i < ipArr.length; i++ ) {
			
			if( ipArr[i].indexOf( "/" ) >= 0 ) {
				
				String[] tempArr = ipArr[i].split( "/" );

				boolean tResult = false;
				
				Integer startNum = Integer.valueOf( tempArr[0] );
				Integer endNum = Integer.valueOf( tempArr[1] );
				
				for( int j = startNum; j <= endNum; j++ ) {
					if( String.valueOf( j ).equals( userIpArr[i] ) ) {
						tResult = true;
					}
				}
				
				if( !tResult ) {
					result = false;
				}
				
			}
			else {
				
				if( !ipArr[i].equals( userIpArr[i] ) ) {
					result = false;
					break;
				}
				
			}
			
		}
		
		return result;
		
	}
	
	private boolean checkIpAll( String ip, String userIp ) throws Exception {
		
		boolean result = true;
		String[] ipArr = ip.split( "\\." );
		String[] userIpArr = userIp.split( "\\." );
		
		for( int i = 0; i < ipArr.length; i++ ) {
			
			if( ipArr[i].indexOf( "*" ) < 0 ) {
				
				if( !ipArr[i].equals( userIpArr[i] ) ) {
					result = false;
					break;
				}
				
			}
			
		}
		
		return true;
		
	}
	
}

 

 

- sys.properties

#Ip체크
# xxx.xxx.xxx.xxx - 단일 아이피
# xxx.xxx.xxx.1/255 - 아이피 대역대
# xxx.xxx.xxx.* - 모든 대역대
# 구분값 (,)
accessIp = *
반응형

관련글 더보기

댓글 영역