セッションを使ったカスタム認証(認証処理)

広告

ログイン画面から送られてきたユーザー名とパスワードでデータベース内のデータを照合してユーザーの認証を行います。

実際の処理としてはユーザー管理用のテーブルをユーザー名とパスワードが一致するレコードがあるかどうかを検索して、あれば認証すると言う単純な処理を行います。

データベースはJDBCRealmレルムを試した時に作成したMySQLのデータベースをそのまま使います。「auth」データベースの中の「user_table」テーブルを使います。データベースへの接続は「init」メソッドで行い、切断は「destory」メソッドで行います。

protected Connection conn = null;

public void init() throws ServletException{
  String url = "jdbc:mysql://localhost/auth";
  String user = "authtest";
  String password = "authtest";

  try {
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    conn = DriverManager.getConnection(url, user, password);
  }catch (ClassNotFoundException e){
    log("ClassNotFoundException:" + e.getMessage());
  }catch (SQLException e){
    log("SQLException:" + e.getMessage());
  }catch (Exception e){
    log("Exception:" + e.getMessage());
  }
}

public void destory(){
  try{
    if (conn != null){
      conn.close();
    }
  }catch (SQLException e){
    log("SQLException:" + e.getMessage());
  }
}

パラメータで受け取ったユーザー名とパスワードを使って「user_table」からレコードを取得します。

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

String sql = "SELECT * FROM user_table WHERE user = ? && pass = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);

pstmt.setString(1, user);
pstmt.setString(2, pass);
ResultSet rs = pstmt.executeQuery();

今回は認証したユーザーが誰かは気にしないので、取得した「ResultSet」オブジェクトが空でなければ認証が通ったことにして終了です。

実際に試してみる

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

まず「LoginCheck」サーブレットを書き換えてみます。

LoginCheck2.java

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

public class LoginCheck2 extends HttpServlet {
  protected Connection conn = null;

  public void init() throws ServletException{
    String url = "jdbc:mysql://localhost/auth";
    String user = "authtest";
    String password = "authtest";

    try {
      Class.forName("com.mysql.jdbc.Driver").newInstance();
      conn = DriverManager.getConnection(url, user, password);
    }catch (ClassNotFoundException e){
      log("ClassNotFoundException:" + e.getMessage());
    }catch (SQLException e){
      log("SQLException:" + e.getMessage());
    }catch (Exception e){
      log("Exception:" + e.getMessage());
    }
  }

  public void destory(){
    try{
      if (conn != null){
        conn.close();
      }
    }catch (SQLException e){
      log("SQLException:" + e.getMessage());
    }
  }

  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;
    }

    try {
      String sql = "SELECT * FROM user_table WHERE user = ? && pass = ?";
      PreparedStatement pstmt = conn.prepareStatement(sql);

      pstmt.setString(1, user);
      pstmt.setString(2, pass);
      ResultSet rs = pstmt.executeQuery();

      if (rs.next()){
        return true;
      }else{
        return false;
      }
    }catch (SQLException e){
      log("SQLException:" + e.getMessage());
      return false;
    }
  }
}

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>LoginCheck2</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」サーブレットが呼ばれますが、認証に失敗するので再度ログイン画面が表示されます。

カスタム認証

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

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

カスタム認証

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

カスタム認証

それでは次のページでログアウトの処理を付け加えます。

( Written by Tatsuo Ikura )

関連記事 (一部広告含む)