본문 바로가기

Web For All/Struts

struts2 인터셉터를 이용한 로그인 세션

작업 개요

  • 로그인 했는지 검사하여, 로그인 하지 않았다면, 로그인 페이지나 특정 XML 메세지를 보내기 위한 인터셉터를 작성한다.
  • 액션 요청에 대해서만 검증할 것이기 때문에 인터셉터에서의 적용이 적합하겠다.
  • 적용 작업은 아래와 같다.
    • 커스텀 인터셉터 작성하기
    • struts.xml에 인터셉터 정의하여 적용하기
  • 처리 프로세스 플로우차트 보기

[편집] 커스텀 인터셉터 작성하기

  • // TODO 부분(2군데..)는 해당 애플리케이션에 맞게 작성해 주어야 하겠다.
    • 첫번째는 proccessDeniedResponse() 메소드에 있으며, 마이플랫폼 메세지를 던져주는 부분이다.
    • 두번째는 isLogined()메소드에 있으며, 세션상에 로그인 정보를 검사하는 부분이다.
  • 소스 설명
    • 인터셉터가 작동하는 메인 메소드는 intercept(ActionInvocation invocation) 메소드이다.
      • 여기서 허용 URL인지, 로그인 했는지 검사하는 것과 요청을 거부하는 프로세스를 처리한다.
    • excludeActions 변수는 로그인 했는지 검사하는 것에서 제외하기 위한 액션들이 있는 경우 사용한다.
    • redirectWebPage 변수는 일반 웹 요청시 액션 수행 거부(로그인 하지 않음)에 대해 라디이렉트 할 페이지를 지정한다.
      • 이와 마찬가지로 마이플랫폼 요청에 대한 거부 메세지도 파라미터화 하여 처리할 수 있겠다.
public class LoginSessionCheckInterceptor extends AbstractInterceptor{
 
    private static Log log = LogFactory.getLog(LoginSessionCheckInterceptor.class);
	
    protected Set excludeActions = null;
    
    protected String redirectWebPage = "/index.html"; // default page if not setted by param.    
 
    public void setExcludeActions(String excludeActions) {
        this.excludeActions = TextParseUtil.commaDelimitedStringToSet(excludeActions);
    }
    
	public void setRedirectWebPage(String redirectWebPage) {
		if( StringUtils.isNotBlank(redirectWebPage)) this.redirectWebPage = redirectWebPage;
	}
    
	/**
	 * check and deny the request unless rquested action is available action without login or has authenticated session.  
	 * 
	 */
	public String intercept(ActionInvocation invocation) throws Exception {
		
		if( isAvailableActionWithoutLogin() ){ // check if action is available action without login
			return invocation.invoke(); // execute action
		}
		else{
			if( isLogined()){ // check if logged in or not
				return invocation.invoke(); // execute action
			}
			else{
				proccessDeniedResponse(); // redirect to login page, or send denial xml message
				return null;
			}
		}
	}
	
	private void proccessDeniedResponse() throws IOException { 
		if( isMiplatformRequest(ServletActionContext.getRequest()) ){
			// TODO send MiResponse denial message
			// example is following :
			// 		MiResponse miresponse = new MiResponse(ServletActionContext.getResponse());
			// 		miresponse.error("-1","sessionout");
		}
		else{
			String redirectUrl = null;
			if( redirectWebPage.startsWith("/") || redirectWebPage.startsWith("\\")){
				redirectUrl = ServletActionContext.getRequest().getContextPath() + redirectWebPage;
			}else{
				redirectUrl = ServletActionContext.getRequest().getContextPath() + "/" +redirectWebPage;
			}			
			ServletActionContext.getResponse().sendRedirect(redirectUrl);
		}
	}
 
	private boolean isMiplatformRequest(HttpServletRequest request) {
		String agent = request.getHeader("User-Agent");		
		if( agent != null && ( agent.indexOf("MiPlatform") != -1 ) ){
			return true;
		}else{
			return false;
		}
	}
 
	private boolean isLogined() {
		HttpSession session = ServletActionContext.getRequest().getSession(false);
		if( null == session) return false;
		
		// TODO check if session is logined session.
		// example is following : 
		// 		if( isLogedin(session) ) return true;
		// 		else return false;
		
		return false;
	}
 
	private boolean isAvailableActionWithoutLogin() {
		String requestedResouece = getRequestedResource(ServletActionContext.getRequest());
		if( log.isDebugEnabled() ) log.debug("Requested action resource : " + requestedResouece);
		
		String action = null;
		Iterator excludeActionsIter = excludeActions.iterator();
		while( excludeActionsIter.hasNext() ){
			action = (String) excludeActionsIter.next();
			if( requestedResouece.equals(action) ) return true;	
		}
		
		return false;
	}
 
	private String getRequestedResource(HttpServletRequest request){
		String requestedResouece = null;
		
		String contextPath = request.getContextPath();
		String requestedUri = request.getRequestURI();
		
		if( "/".equals(contextPath) ){
			requestedResouece = requestedUri;
		}
		else{
			requestedResouece = requestedUri.substring(contextPath.length());
		}		
		return requestedResouece;
	}
}

[편집] 인터셉터의 적용

  • struts.xml에 우리가 작성한 인터셉터를 정의하고, 이를 이용하여 인터셉터 스택을 만든다.
  • 정의가 끝나면 common 패키지를 상속하는 다른 모든 스트럿츠2 패키지들을 모두 디폴트 인터셉터 스택이 commonStack이 될 것이다.
    • 여기서는 스트럿츠의 디폴트 인터셉터 스택을 다소 최적화하여 사용하고 있다.
    • loginCheck 인터셉터의 정의 부분과 스택에서 사용하는 부분을 주의하여 살펴 본다.
    • excludeActions 파라미터에는 샘플로 login.action과 /lab1/hello2.action은 로그인을 하지 않아도 수행할 수 있는 액션으로 정의해 놓았다.
    • excludeActions 아래에 <param name="redirectWebPage">/login.jsp</param>를 추가 작성하면, 로그인 하지 않고 접근하는 액션 일반 웹 액션 요청들을 거부하고 login.jsp로 리다이렉트 하게 될 것이다.
    • [과제] 웹 요청 말고도 마이플랫폼 요청을 거부하는 경우에 사용하는 에러코드와 에러메시지도 파라미터로 처리하도록 개선해 보자.
<struts>
	<package name="common" extends="struts-default" namespace="">	
		<interceptors>
			<interceptor name="loginCheck" class="kr.ac.catholic.web.struts2.interceptor.LoginSessionCheckInterceptor"/>
			<interceptor-stack name="commonStack">
			                <interceptor-ref name="exception"/>
			                <interceptor-ref name="loginCheck">
			                	<param name="excludeActions">login.action, /lab1/hello2.action</param>
			                </interceptor-ref>
			                <interceptor-ref name="alias"/>
			                <interceptor-ref name="servletConfig"/>
			                <interceptor-ref name="prepare"/>
			                <interceptor-ref name="i18n"/>
			                <interceptor-ref name="chain"/>
			                <interceptor-ref name="debugging"/>
			                <interceptor-ref name="fileUpload"/>
			                <interceptor-ref name="checkbox"/>
			                <interceptor-ref name="staticParams"/>
			                <interceptor-ref name="params">
			                  <param name="excludeParams">dojo\..*</param>
			                </interceptor-ref>
			                <interceptor-ref name="conversionError"/>
			                <interceptor-ref name="validation">
			                    <param name="excludeMethods">input,back,cancel,browse</param>
			                </interceptor-ref>
			</interceptor-stack>
		</interceptors>
		
		<default-interceptor-ref name="commonStack"/>
		
	</package>
</struts>


참조사이트)