2012-07-01 4 views
4

내 간단한 JSP 기반 응용 프로그램에서 다시 사용하기 위해 로그인과 세션 구조를 만들었습니다.로그인 페이지에서 새로 고침시 세션 시간 초과

web.xml을 (1 분 제한 시간 내 문제를 테스트하는 것입니다) :

<session-config><session-timeout>1</session-timeout></session-config> 

<filter><filter-name>Access</filter-name><filter-class>com.app.Access</filter-class></filter> 
<filter-mapping><filter-name>Access</filter-name><url-pattern>*</url-pattern></filter-mapping> 

<servlet><servlet-name>Login</servlet-name><servlet-class>com.app.Login</servlet-class></servlet> 
<servlet-mapping><servlet-name>Login</servlet-name><url-pattern>/login</url-pattern></servlet-mapping> 

Access.java 필터 :

// Check if the page's the login or if the user logged, else asks login 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { 
    HttpServletRequest httpRequest = (HttpServletRequest) request; 
    boolean logged = httpRequest.getSession(false) != null && httpRequest.getSession().getAttribute("user") != null; 
    if (httpRequest.getServletPath().equals("/login") || logged) 
     chain.doFilter(request, response); 
    else 
     ((HttpServletResponse) response).sendRedirect(httpRequest.getContextPath() + "/login"); 
} 

Login.java 그것은이 같은거야 서블릿 (테스트를 위해 인증 단축) :

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) 
     request.setAttribute("failure", "session timeout"); 
    request.getSession().setAttribute("user", null); 
    request.getRequestDispatcher("login.jsp").forward(request, response); 
} 

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    request.getSession().setAttribute("user", new User()); 
    response.sendRedirect(""); 
} 

그리고 의 login.jsp 페이지에서의 WebContent의 루트에, 또는 로그인 실패세션 시간 제한을받을 충당 인증 innerHTML을하고 $ {실패} 필드와 <form action="login" method="post"> 형태를 갖는다 메시지.

이 구조는 완벽하게 작동합니다. 세션을 가로 채고, 로그인을 요청하고, 세션과 인증을 모두 확인합니다. 그러나 작은 결함이 있습니다 : 로그인 페이지에 있고 시간 초과 후 페이지를 새로 고치면 (F5 키 또는 URL에서 Enter 키를 누르면) 페이지 $ {failure}에 "session timeout"메시지를 수신하여 표시합니다.

이전 페이지가 로그인 페이지라는 사실을 아직 알지 못했습니다. 성공없이 약 5 가지 방법을 시도했습니다. request.getHeader("Referer")lastWish 태그 라이브러리가 있습니다.

답변

2

한 가지 방법은 공개적으로 액세스 할 수있는 JSP (예 : 로그인 페이지)를 이 아닌으로 설정하여 세션을 생성하는 것입니다. JSP 페이지 요청은 기본적으로 암시 적으로 세션을 만듭니다. null을 반환합니다

<%@page session="false" %> 

이 방법 request.getRequestedSessionId()을 따라서 타임 아웃 검사가 생략됩니다 이것은 JSP의 맨 위에 다음 줄을 추가하여 달성 될 수있다. 세션은이 방법으로 실제로 사용자에게 로그인 할 때만 만들어집니다. 난 그 말이 없기 때문에 단지 서블릿에서 다음 줄을 제거 거라고 여전히 세션을 만들 것입니다 :

request.getSession().setAttribute("user", null); 
+0

내가 좋아하는 뭔가를 알고하지 않았다을 그게 끝날 수있어! 사용자가 로그인 페이지를 수동으로 가져 왔을 때를 대비하여 사용자를 재설정하는 방법을 추가했지만 솔루션을 사용하면이를 제거하는 것이 더 좋습니다. 대단히 감사합니다, BalusC! –

+0

당신을 진심으로 환영합니다. 당신이 여기 새로 왔기 때문에 구체적인 문제를 푸는데 도움이 될 때마다 대답을 표시하는 것을 잊지 마십시오. [답변 수락 방법은 무엇입니까?] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) – BalusC

+1

@ Trevor : 멋진 엣지 케이스. 보통 평균 자존심이있는 웹 사이트에서는 이미 로그인 한 사용자가 "로그인"링크를 보지 못합니다 (UX 관점에서 혼란 스럽기 때문에) URL을 강제하거나 링크/북마크를 따라 방문하려고하면 결과가 나타납니다 메인 페이지 리디렉션에서 "이미 로그인하셨습니다."라는 메시지가 표시 될 수 있습니다.리디렉션의 경우 필터를 사용할 수 있습니다 (아마 이미 사용하고있는 것과 동일한 인증 필터 일 수 있습니다). – BalusC

0

난 그냥 이런 식으로 작업을 수행합니다

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
    HttpServletRequest httpReq = (HttpServletRequest)request; 
    String servletPath = httpReq.getServletPath(); 
    HttpSession session = httpReq.getSession(); 
    String redirectUrl = "/login.jsp"; 
    if (
      (servletPath.endsWith("login.jsp")) || 
      (servletPath.endsWith("rss.html")) || 
      (servletPath.endsWith("httperror403.html")) || 
      (servletPath.endsWith("httperror500.html")) || 
      (servletPath.endsWith("imageMark.do"))|| 
      (servletPath.indexOf("/api.do") != -1) || 
      (servletPath.indexOf("/help/") != -1)){ 
     chain.doFilter(request, response); 
    } else if (session == null) { 
     httpReq.getRequestDispatcher(redirectUrl).forward(request, response); 
    } else { 
     SystemUser user = (SystemUser)session.getAttribute("user"); 
     if (user == null){ 
      if (session != null){ 
       session.invalidate(); 
      } 
      httpReq.getRequestDispatcher(redirectUrl).forward(request, response); 
     } else { 
      chain.doFilter(request, response); 
     } 
    } 
} 
+0

이것이 OP의 구체적 질문에 정확히 어떻게 대답합니까? 그건 그렇고, 당신의 코드에 논리 결함이 있습니다. 'session'은이 구조체에서 결코 ** null이 아닙니다. – BalusC