19

ユーザーが自分のアカウントにサインインしてからブラウザーを閉じた Web サイトを見たことがあります。

ブラウザを閉じて再度開いた後も、アカウントはサインインしたままです。

しかし、一部の Web サイトでは、そのようにすることはできません。

セッションまたはCookieと見なされることに混乱していますか?

自分の Web サイトをそのようにサインインさせたい場合、または を設定する必要がありますsession.setMaxInactiveInterval()cookie.setMaxAge()?

4

2 に答える 2

11

正解には多くの欠陥があります。そこにある私のコメントを参照してください。問題は実際には簡単です。永続的なデータストア (SQL データベースなど) が必要になります。同様に使用できますServletContextが、ユーザーはサーバーの再起動またはアプリケーションの再デプロイ後にログアウトされます。HashMapinを使用する場合はServletContext、より多くのスレッドから同時にアクセスされる可能性があるため、適切に同期することを忘れないでください。

サーバーのセッションとそのIDでハッキングしないでください。それはあなたの管理下になく、サーバーが元のセッションを期限切れにした後にJSESSIONIDを含むリクエストが表示された場合、一部のサーバーはセッションIDを変更します。独自のクッキーをロールします。

基本的に必要なもの:

  • 安全にランダムな値を持つ、永続的ではない独自の Cookie
  • データストア
  • javax.servlet.Filterログインを確認する

フィルタの実装は次のようになります。

public class LoginFilter implements Filter {

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

        // Java 1.8 stream API used here
        Cookie loginCookie = Arrays.stream(req.getCookies()).filter(c -> c.getName()
                .equals("MY_SESSION_COOKIE")).findAny().orElse(null);

        // if we don't have the user already in session, check our cookie MY_SESSION_COOKIE
        if (req.getSession().getAttribute("currentUser") == null) {
            // if the cookie is not present, add it
            if (loginCookie == null) {
                loginCookie = new Cookie("MY_SESSION_COOKIE", UUID.randomUUID().toString());
                // Store that cookie only for our app. You can store it under "/", 
                // if you wish to cover all webapps on the server, but the same datastore
                // needs to be available for all webapps.
                loginCookie.setPath(req.getContextPath());
                loginCookie.setMaxAge(DAYS.toSeconds(1)); // valid for one day, choose your value
                resp.addCookie(loginCookie);
            }
            // if we have our cookie, check it
            else {
                String userId = datastore.getLoggedUserForToken(loginCookie.getValue());
                // the datastore returned null, if it does not know the token, or 
                // if the token is expired
                req.getSession().setAttribute("currentUser", userId);
            }
        }
        else {
            if (loginCookie != null)
                datastore.updateTokenLastActivity(loginCookie.getValue());
        }

        // if we still don't have the userId, forward to login
        if (req.getSession().getAttribute("currentUser") == null)
            resp.sendRedirect("login.jsp");
        // else return the requested resource
        else
            chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

}

ユーザーがログインしたら、MY_SEESSION_COOKIE の値を とともにデータストアに追加し、userIdログアウト時に削除する必要があります。また、有効期限をデータストアに保存し、トークンを受け入れる前に確認する必要があります。maxAge プロパティに関するブラウザーに依存しないでください。

また、データストアのクリーンアップを追加して、未処理の Cookie が永久に残るのを防ぐことを忘れないでください。

上記のコードは実際にはテストされていません。いくつかの癖があるかもしれませんが、基本的な考え方は機能するはずです。少なくとも、受け入れられているソリューションよりもはるかに優れています。

于 2015-05-15T07:44:31.567 に答える