セッションを使ったカスタム認証(ログイン画面)

広告

前回中身を省略したログイン画面を作成してみます。

基本的にはFORM認証の時に作成したログイン用のHTMLページとほぼ同じ内容のものです。フォームの送信先が自分で作成したサーブレットである点と、HTMLページではなくサーブレットで行っている点が違うくらいです。

またログインに失敗した場合も同じサーブレットを再度呼び出します。その時、エラーメッセージを表示出来るようにしておきましょう。これもセッションを使います。

Login2.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Login2 extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{

    response.setContentType("text/html; charset=Shift_JIS");
    PrintWriter out = response.getWriter();

    out.println("<html>");
    out.println("<head>");
    out.println("<title>ログインページ</title>");
    out.println("</head>");
    out.println("<body>");

    out.println("<h1>ログイン画面</h1>");

    HttpSession session = request.getSession(true);

    /* 認証失敗から呼び出されたのかどうか */
    Object status = session.getAttribute("status");

    if (status != null){
      out.println("<p>認証に失敗しました</p>");
      out.println("<p>再度ユーザー名とパスワードを入力して下さい</p>");

      session.setAttribute("status", null);
    }

    out.println("<form method=\"POST\" action=\"/auth/LoginCheck\" name=\"loginform\">");
    out.println("<table>");
    out.println("<tr>");
    out.println("<td>ユーザー名</td>");
    out.println("<td><input type=\"text\" name=\"user\" size=\"32\"></td>");
    out.println("</tr>");
    out.println("<tr>");
    out.println("<td>パスワード</td>");
    out.println("<td><input type=\"password\" name=\"pass\" size=\"32\"></td>");
    out.println("</tr>");
    out.println("<tr>");
    out.println("<td><input type=\"submit\" value=\"login\"></td>");
    out.println("<td><input type=\"reset\" value=\"reset\"></td>");
    out.println("</tr>");
    out.println("</table>");
    out.println("</form>");

    out.println("</body>");
    out.println("</html>");
  }
}

フォームを表示する前に、セッションに含まれる「status」の値を調べます。「status」に何か入っていた場合は一度認証に失敗し再度表示されて場合ですので、エラーメッセージを表示するようにします。

認証チェックサーブレット

先ほどのフォームからPOSTの送信先が「LoginCheck」サーブレットです。本来は入力されたユーザー名とパスワードを元にデータベースを検索し、ユーザーが存在するかどうかを確認するのですが、今回は暫定のためユーザー名とパスワードの両方に値が入力されていれば認証OKとします。

認証OKであれば、セッションの「login」に値を設定して、本来アクセスするはずだったURLへリダイレクトします。認証に失敗した場合はセッションの「status」に値を設定して「Login」サーブレットを再度読み出します。

LoginCheck1.java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class LoginCheck1 extends HttpServlet {
  public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{

    response.setContentType("text/html; charset=Shift_JIS");
    PrintWriter out = response.getWriter();

    String user = request.getParameter("user");
    String pass = request.getParameter("pass");

    HttpSession session = request.getSession(true);

    boolean check = authUser(user, pass);
    if (check){
      /* 認証済みにセット */
      session.setAttribute("login", "OK");

      /* 本来のアクセス先へ飛ばす */
      String target = (String)session.getAttribute("target");
      response.sendRedirect(target);
    }else{
      /* 認証に失敗したら、ログイン画面に戻す */
      session.setAttribute("status", "Not Auth");
      response.sendRedirect("/auth/Login");
    }
  }

  protected boolean authUser(String user, String pass){
    /* 取りあえずユーザー名とパスワードが入力されていれば認証する */
    if (user == null || user.length() == 0 || pass == null || pass.length() == 0){
      return false;
    }

    return true;
  }
}

実際に試してみる

ではこの時点でのテストを行っておきます。

web.xmlファイルを次のように修正して下さい。

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">

  <servlet>
    <servlet-name>CustomAuth1</servlet-name>
    <servlet-class>CustomAuth1</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>CustomAuth1</servlet-name>
    <url-pattern>/CustomAuth1</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>CustomAuth2</servlet-name>
    <servlet-class>CustomAuth2</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>CustomAuth2</servlet-name>
    <url-pattern>/CustomAuth2</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>Login</servlet-name>
    <servlet-class>Login2</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Login</servlet-name>
    <url-pattern>/Login</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>LoginCheck</servlet-name>
    <servlet-class>LoginCheck1</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>LoginCheck</servlet-name>
    <url-pattern>/LoginCheck</url-pattern>
  </servlet-mapping>
</web-app>

それでは一度サーブレットを再起動してから、ブラウザで「http://localhost:8080/auth/CustomAuth1」へアクセスして下さい。

カスタム認証

「CustomAuth1」サーブレットへアクセスしてもセッションに必要な情報が保存されていませんので「Login」サーブレットへリダイレクトされます。今回はログインフォームが表示されます。

では先に認証失敗する方を試してみます。ユーザー名だけに値を入力してパスワードは空欄のままで「login」ボタンをクリックして下さい。

カスタム認証

すると「LoginCheck」サーブレットが呼ばれますが、認証に失敗するので再度ログイン画面が表示されます。

カスタム認証

一度認証に失敗しているのでエラーメッセージも画面に表示されています。

では今度はユーザー名とパスワードに値を入力してから「login」ボタンをクリックして下さい。

カスタム認証

「LoginCheck」サーブレットが呼ばれ、認証に通りますのでセッションに値を設定したあと本来呼び出したサーブレットへリダイレクトされます。今度はセッションに適切な値が設定してあるため、表示が行われます。

カスタム認証

それでは次のページでデータベースを使ってユーザーの認証を行ってみます。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。