web-dev-qa-db-ja.com

Java Webアプリケーションでセッションの有効期限が切れたときにログインページにリダイレクトする方法は?

JBoss AS 5でWebアプリケーションを実行しています。サーバーへのすべてのリクエストをインターセプトするサーブレットフィルターもあります。次に、セッションの有効期限が切れた場合に、ユーザーをログインページにリダイレクトします。フィルタでこの「isSessionExpired()」チェックを実行し、それに応じてユーザーをリダイレクトする必要があります。どうすればいいのですか?以下のように、web.xmlでセッションの時間制限を設定しています。

<session-config>
    <session-timeout>15</session-timeout>
</session-config>
45
Veera

Filter を使用して、次のテストを実行できます。

HttpSession session = request.getSession(false);// don't create if it doesn't exist
if(session != null && !session.isNew()) {
    chain.doFilter(request, response);
} else {
    response.sendRedirect("/login.jsp");
}

上記のコードはテストされていません

ただし、これは最も広範なソリューションではありません。また、セッションが新しいものではないため、ユーザーがログインしている必要があると想定する前に、セッションでドメイン固有のオブジェクトまたはフラグが使用できることをテストする必要があります。Be paranoid

55
Alex

Java Webアプリケーション?でセッションの有効期限が切れたときにログインページにリダイレクトする方法

これは間違った質問です。 「ユーザーがログインしていない」場合と「セッションの有効期限が切れている」場合を区別する必要があります。基本的に、ユーザーがログインしていないときにログインページにリダイレクトします。セッションの有効期限が切れたときではありません。現在受け入れられている回答は、HttpSession#isNew()のみをチェックします。ただし、セッションがJSPによって暗黙的に作成された場合などに、ユーザーが同じセッションで複数のリクエストを送信した場合、これは明らかに失敗します。例えば。ログインページでF5キーを押すだけです。

前述のように、代わりにユーザーがログインしているかどうかを確認する必要があります。 _j_security_check_、Shiro、Spring Securityなどの標準認証フレームワークがすでに透過的に管理している間にこの種の質問をしているという事実を考えると(したがって、この種の質問をする必要はありません) 、それはあなたが自家製の認証アプローチを使用していることを意味するだけです。

ログインしたユーザーをセッションのログインに保存すると仮定します servlet 以下のように:

_@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @EJB
    private UserService userService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);

        if (user != null) {
            request.getSession().setAttribute("user", user);
            response.sendRedirect(request.getContextPath() + "/home");
        } else {
            request.setAttribute("error", "Unknown login, try again");
            doGet(request, response);
        }
    }

}
_

次に、ログインでそれを確認できます filter 以下のように:

_@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURI = request.getContextPath() + "/login";

        boolean loggedIn = session != null && session.getAttribute("user") != null;
        boolean loginRequest = request.getRequestURI().equals(loginURI);

        if (loggedIn || loginRequest) {
            chain.doFilter(request, response);
        } else {
            response.sendRedirect(loginURI);
        }
    }

    // ...
}
_

脆弱なHttpSession#isNew()チェックをいじる必要はありません。

18
BalusC

次のようなフィルターを使用して行うこともできます。

public class RedirectFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req=(HttpServletRequest)request;

    //check if "role" attribute is null
    if(req.getSession().getAttribute("role")==null) {
        //forward request to login.jsp
        req.getRequestDispatcher("/login.jsp").forward(request, response);
    } else {
        chain.doFilter(request, response);
    }
}
}
8
kafrlust

フィルタ内にこのJavaScriptを挿入すると、このようなログインページが表示されます。これを行わないと、AJAXの呼び出しでログインページが取得され、ログインページの内容が追加されます。

フィルターまたはリダイレクト内に、応答としてこのスクリプトを挿入します。

String scr = "<script>window.location=\""+request.getContextPath()+"/login.do\"</script>";
response.getWriter().write(scr);
5
mukut

セッションの確認は新しいです。

HttpSession session = request.getSession(false);
if (!session.isNew()) {
  // Session is valid
}
else {
  //Session has expired - redirect to login.jsp
}
5
zkarthik

HttpSessionListenerインターフェイスを実装する必要があります。サーバーはセッションタイムアウトを通知します。

このような;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class ApplicationSessionListener implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent event) {
   System.out.println("Session Created");
 }

public void sessionDestroyed(HttpSessionEvent event) {
   //write your logic
   System.out.println("Session Destroyed");
  }
 }

理解を深めるには、この例を確認してください

http://www.myjavarecipes.com/how-to-catch-session-timeouts/

4
Sunil Pidugu

セッションがタイムアウトするまで、通常のリクエストを取得し、その後、Ajaxリクエストを取得します。次の方法で識別できます。

String ajaxRequestHeader = request.getHeader("X-Requested-With");
if ("XMLHttpRequest".equals(ajaxRequestHeader)) {
    response.sendRedirect("/login.jsp");
}
2
Anirudh Jadhav

私はこの可能な解決策を見つけました:

public void logout() {
    ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
    String ctxPath = ((ServletContext) ctx.getContext()).getContextPath();
    try {
        //Use the context of JSF for invalidate the session,
        //without servlet
        ((HttpSession) ctx.getSession(false)).invalidate();
        //redirect with JSF context.
        ctx.redirect(ctxPath + "absolute/path/index.jsp");
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}
0
LoGos