2014-12-12 1 views
0

기본 양식 로그인 인증을 작성했으며 아래는 제 구성입니다. 예상대로 스프링 보안, 세션은 세션 시간 초과 후 로그인하지 않고 생성됩니다.

<http auto-config="true" use-expressions="true"> 
    <request-cache ref="authenticationRequestCache" /> 
    <access-denied-handler error-page="/rest/login?error=denied" /> 
    <form-login login-page="/rest/login"  
     authentication-success-handler-ref="successHandler" 
     authentication-failure-url="/rest/login?error" /> 
    <intercept-url pattern="/rest/devices" access="denyAll" /> 
    <intercept-url pattern="/rest/devices/**" access="denyAll" /> 
    <intercept-url pattern="/rest/super/**" access="hasRole('ROLE_SUPER')" /> 
    <intercept-url pattern="/rest/**" access="isAuthenticated()" /> 
    <intercept-url pattern="/cavirinRest/*" /> 
    <session-management invalid-session-url="/rest/login?error=sessionExpired" 
     session-authentication-strategy-ref="sas" /> 
    <logout invalidate-session="true" logout-success-url="/rest/login" delete-cookies="JSESSIONID"/> 
</http> 

인증은 잘 작동하지만 최근에는 응용 프로그램에 세션 타임 아웃을 추가했다. 내 응용 프로그램은 5 초마다 서버를 폴링하므로 기본 시간 제한이 작동하지 않습니다. 내가 봤 거든 필터와 솔루션 아래에 발견하고 그것을 구현했습니다. web.xml 파일에서

: 타임 아웃이 발생하면, 내 아약스 요청 (내가 크롬에서 볼 - 개발자 도구, 네트워크 탭)

<filter> 
    <filter-name>XhrSessionTimeoutFilter</filter-name> 
    <filter-class>com.cavirin.security.filter.XhrSessionTimeoutFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>XhrSessionTimeoutFilter</filter-name> 
    <url-pattern>/rest/*</url-pattern> 
</filter-mapping> 


<session-config> 
    <!-- Disables URL-based sessions (no more 'jsessionid' in the URL using Tomcat) --> 
    <tracking-mode>COOKIE</tracking-mode> 
    <session-timeout>2</session-timeout> 
</session-config> 


@Override 
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 

    HttpSession session = request.getSession(false); 

    if (session != null) { 
     logger.trace("doFilterInternal(): session object is not null."); 

     session.setMaxInactiveInterval(120); //2 mins for testing //set max inactive interval to 30 mins 

     // if requestURI is not null 
     if (request.getRequestURI() != null) { 

      logger.trace("doFilterInternal(): request.getRequestURI() : {} ", request.getRequestURI()); 

      String ajaxHeader = request.getHeader("X-Requested-With"); 
      logger.trace("doFilterInternal(): ajaxHeader : {} ", ajaxHeader); 

      //if it is an AJAX call 
      if ("XMLHttpRequest".equals(ajaxHeader)) { 
       logger.trace("doFilterInternal(): An AJAX call, set the last access time, if not already set."); 
       Long lastAccess = (Long) session.getAttribute(AJAX_DATA_LAST_ACCESS_TIME); 

       if (lastAccess == null) { 
        logger.trace("doFilterInternal(): Last access time is null, set current time as lastAccess time."); 
        lastAccess = System.currentTimeMillis(); 
        session.setAttribute(AJAX_DATA_LAST_ACCESS_TIME, lastAccess); 
       } else { 
        logger.trace("doFilterInternal(): max interval: {} -- lastAccess: {} -- currentTimeMillis: {} ", 
         + session.getMaxInactiveInterval(), lastAccess, System.currentTimeMillis()); 
        if (((session.getMaxInactiveInterval() * 1000) - (System.currentTimeMillis() - lastAccess)) < 0) { 
         logger.debug("doFilterInternal(): session should be invalidated as inative time execeeded."); 
         session.invalidate(); 
        } 
       } 
      } else { 
       logger.trace("doFilterInternal(): Not an AJAX call."); 
       session.removeAttribute(AJAX_DATA_LAST_ACCESS_TIME); 
      } 
     } 
    } 

    filterChain.doFilter(request, response); 
} 

제한 시간도 잘 작동하지만 그것이 리디렉션으로 (302 개) 상태가됩니다 다른 페이지로 이동하십시오. 세션 시간 초과 오류 메시지가있는 내 로그인 페이지입니다. 나는 아무 것도 클릭하지 않고 다른 2 분 (테스트를 위해 2 분의 타임 아웃을 설정)으로두고, 다시 "세션이 만료되었습니다"라는 로그 메시지를보고 로그인으로 리디렉션됩니다. 나는 새로운 JSESSIONID가 세션 만료 후 작성이 볼 수

RequestMapping(method = RequestMethod.GET) 
public ModelAndView showLogin(Model model, 
           @RequestParam(value = "error", required = false) String errorStr, 
           HttpServletRequest request) { 
    logger.trace("Returning login page view."); 

    String pageToBeLoaded = "rest/login" ; 

    System.out.println("showLogin(): errorStr: " + errorStr); 

    if (errorStr != null) { 

     if (errorStr.equalsIgnoreCase("sessionExpired")) { 
      logger.debug("showLogin(): error: sessionExpired "); 
      System.out.println("showLogin(): error: sessionExpired"); 
      model.addAttribute("error", "Session expired. Please log in again."); 
     } else if (errorStr.equalsIgnoreCase("denied")) { 
      logger.debug("showLogin(): error: denied "); 
      System.out.println("showLogin(): error: denied"); 
      model.addAttribute("error", "Access is denined. This page is for SUPER user only."); 
     } else { 
      model.addAttribute("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION")); 
      System.out.println("showLogin(): error: " + getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION")); 
     } 
    } 
    return new ModelAndView(pageToBeLoaded); 
} 

나는 타임 아웃 후 폴링 서버를 중지하지 않은 것을 알고, 그래서 또 다시 여론 조사, 그러나 1) 세션이 로깅에없이 만드는 방법 응용 프로그램에?

또한 2) 세션 시간 초과 오류 메시지가 표시되지 않습니다.이 메시지는이 페이지로 한 번 이동하여 다시 로그인 페이지로 이동합니다. 사용자가 다시 로그인 할 때까지이 오류 메시지를 보관할 수 없습니다.

모든 포인터?

답변

1

스프링 보안 및 관련 자료에 대한 많은 정보를 읽은 후 ) 1) 세션이 기본적으로 생성되고 (필요한 경우 http 구성, 한 번 세션이 시간 초과되면) 지정된 URL로 자동 리디렉션된다는 사실을 알게되었습니다. invalid-session-url의 세션 관리에 대해 다른 세션을 생성합니다. 스프링 보안 디버그 로그에서이 동작을 관찰했습니다. 세션은 무효화되어 필요한 경우 다른 세션을 생성합니다. 2) 시간 초과 세션이 무효화되면 invalid-session-url로 리디렉션됩니다. 하지만 내 아약스는 같은 페이지에서 폴링을 유지하고 다른 세션이 만들어지고 보안 웹 페이지에 액세스하기 위해 인증을 찾고 있으므로 리디렉션은 내 로그인 페이지에서 발생하지만 이번에는 세션 시간 초과 오류가 발생하지 않습니다.

관련 문제