Javaサーブレットでログイン・ログアウト機能を実装する方法【フィルターで未ログイン時のアクセス制限】

1. ログイン機能の実装

まず、ログイン機能の基本を作成します。ここでは、データベースでユーザー情報を確認し、認証成功時にセッションを生成する方法を紹介します。

ログインの流れ

  1. ユーザーIDとパスワードをフォームから受け取る。
  2. DAO(Data Access Object)を使ってデータベースでユーザー情報を確認。
  3. 認証成功時にセッションを生成し、ユーザーIDを保存。
  4. 認証失敗時はエラーメッセージを表示。

LoginCon.java(コントローラー):

package controller;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import model.StoreDao;

public class LoginCon extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userId = request.getParameter("userId");
        String password = request.getParameter("password");

        // デバッグ用出力
        System.out.println("入力されたユーザーID: " + userId);
        System.out.println("入力されたパスワード: " + password);

        // 認証処理
        StoreDao userDao = new StoreDao();
        boolean isAuthenticated = userDao.authenticate(userId, password);

        if (isAuthenticated) {
            HttpSession session = request.getSession();
            session.setAttribute("userId", userId);
            response.sendRedirect("ListCon"); // ログイン成功後のページにリダイレクト
        } else {
            request.setAttribute("errorMessage", "ユーザーIDまたはパスワードが間違っています。");
            RequestDispatcher dispatcher = request.getRequestDispatcher("Login.jsp");
            dispatcher.forward(request, response);
        }
    }
}

Login.jsp(ログイン画面):

<form action="LoginCon" method="post">
    <div>
        <label for="userId">ユーザーID:</label>
        <input type="text" id="userId" name="userId" required>
    </div>
    <div>
        <label for="password">パスワード:</label>
        <input type="password" id="password" name="password" required>
    </div>
    <button type="submit">ログイン</button>
</form>

2. ログアウト機能の実装

ログアウトは、セッションを無効化してログイン画面にリダイレクトするだけで実現できます。

Logout.java(ログアウト用サーブレット):

package controller;

import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class Logout extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession(false); // セッションが存在しない場合はnullを返す
        if (session != null) {
            session.invalidate(); // セッションを無効化
        }
        response.sendRedirect("Login.jsp"); // ログイン画面にリダイレクト
    }
}

Logout.jsp(ログアウトリンク):

<a href="Logout">ログアウト</a>

3. フィルターで未ログイン時のアクセス制限

未ログイン時に特定のページへアクセスできないようにするには、サーブレットフィルターを使います。

LoginFilter.java(フィルター):

package filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        HttpSession session = req.getSession(false);
        String loginURI = req.getContextPath() + "/Login.jsp";

        boolean loggedIn = (session != null && session.getAttribute("userId") != null);
        boolean loginRequest = req.getRequestURI().equals(loginURI) || req.getRequestURI().endsWith("/LoginCon");

        if (loggedIn || loginRequest) {
            chain.doFilter(request, response); // 次のフィルターまたはサーブレットへ進む
        } else {
            res.sendRedirect(loginURI); // 未ログインの場合はログイン画面へリダイレクト
        }
    }

    public void init(FilterConfig fConfig) throws ServletException {}
    public void destroy() {}
}

web.xml(フィルターマッピング):

<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4. 注意点とベストプラクティス

  1. 静的リソースの除外
    フィルターでCSSやJavaScriptファイルも制限されてしまうと、ログイン画面のデザインが崩れます。リクエストURIをチェックして除外しましょう。
  2. セッションの有効期限
    セッションタイムアウトをweb.xmlで設定できます。
<session-config>
    <session-timeout>30</session-timeout> <!-- 30分 -->
</session-config>

  1. 複数のフィルター
    他にも認可フィルターやCSRF対策フィルターを組み合わせると、セキュリティを向上できます。

5. 実際の動作確認

これで以下の機能が完成します:

  • ログインしていない状態で、商品一覧や登録ページにアクセスするとログイン画面へリダイレクト。
  • ログイン成功後、ユーザーごとにセッションが割り振られ、別ユーザーのデータと干渉しない。
  • ログアウト時はセッションが無効化され、再ログインが必要。

良かったらフォローお願いします

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です