2015年9月12日土曜日

Glassfish+Derby+JDBCレルムについて(ソースコード解説)

JDBCレルムについてソースコード内容について概要を記述。
下記GitHubのコードの解説である。
https://github.com/Fufuhu/SimpleAuthentication

NetBeans上でMavenのWebプロジェクトで作成している。


Servletとjspだけで構成されたシンプルな構成になっている。
(Webページディレクトリ直下のindex.jspは無視してもらって構いません。)

■画面遷移について

以下のような形で画面遷移を構成しています。


index.jspがログインページLoginServletにてJDBCレルム認証を実行後、
認証を通過すればtoppage.jsp, 失敗すればerror.jspに遷移する。


■index.jsp
ログインページ。ユーザ名とパスワードの入力したのちに、
ログインボタンクリックで、LoginServletを呼び出し、JDBCレルム
認証を実行することができる。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>ログイン</title>
    </head>
    <body>
        ログイン情報<br/>
        <form method="POST" action="../LoginServlet">
            ユーザ名:<input type="text" name="username"/> <br/>
            パスワード:<input type="password" name="password"/><br/>
            <input type="submit" method="GET" value="ログイン"/>
        </form>
    </body>
</html>



■LoginServlet(一部抜粋)
42行目のrequest.login(username, password);でJDBCレルム認証を実行している。
index.jspで入力されたユーザ名、パスワードの内容に応じてログイン可否を判断している。
loginメソッドで認証ができれば、そのままtoppage.jspへの遷移を続行。(ユーザ認証情報がセッションに含まれるようになる。)できなければServletExceptionがスローされるので、error.jspに遷移する。

package authentication;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author USER
 */
@WebServlet(name = "LoginServlet", urlPatterns = {"/LoginServlet"})
public class LoginServlet extends HttpServlet {

   
    private final String topPage = "/login/toppage.jsp";
    private final String errorPage = "/login/error.jsp";
    /**
     *
     * @param request servlet request
     * @param response servlet response
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        response.setContentType("text/html;charset=UTF-8");
            String username = request.getParameter("username");
            String password = request.getParameter("password");
           
            ServletContext sc = getServletContext();
           
            try {
                //JDBCレルム認証部分(認証に失敗すると例外をスロー)
                request.login(username, password);
            } catch (ServletException ex) {
                Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
                try {
                    sc.getRequestDispatcher(errorPage).forward(request, response);
                } catch (ServletException ex1) {
                    Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }
            try {
                sc.getRequestDispatcher(topPage).forward(request, response);
            } catch (ServletException ex) {
                Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
            }
    } 
    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

■toppage.jsp
仮のトップページ。ウェルカムメッセージと、
ログアウトのための処理呼び出しが可能なだけ。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>トップページ</title>
    </head>
    <body>
        <h1>ログインに成功しました。</h1><br/>
        <form action="./LogoutServlet">
            ${param["username"]}様、いらっしゃいませ。<br/>
            <input type="submit" value="ログアウト"/>
        </form>
    </body>
</html>

■LogoutServlet(一部抜粋)
request.getSession().invalidate();でセッション情報を明示的に破棄するとともに
request.logout();でログアウト処理を実行している。

package authentication;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author USER
 */
@WebServlet(name = "LogoutServlet", urlPatterns = {"/LogoutServlet"})
public class LogoutServlet extends HttpServlet {

    private final String indexPage = "./login/index.jsp";
    private final String errorPage = "./login/error.jsp";
    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     */
    /**
     * @param request servlet request
     * @param response servlet response
     * @throws java.io.IOException
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        //セッションを明示的に破棄する。
        request.getSession().invalidate();
        ServletContext sc = getServletContext();
       
        try {
           //認証からのログアウトを行う処理。
            request.logout();
        } catch (ServletException ex) {
            Logger.getLogger(LogoutServlet.class.getName()).log(Level.SEVERE, null, ex);
            try {
                sc.getRequestDispatcher(errorPage).forward(request, response);
            } catch (ServletException ex1) {
                Logger.getLogger(LogoutServlet.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
        response.sendRedirect(indexPage);      
    }
    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}


■error.jsp
ログイン処理時にrequest.login()に失敗するとこちらのページに遷移する。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>ログイン失敗</h1><br/>
        <a href="./index.jsp">ログインページへ</a>
    </body>
</html>


次の記事では、コードではなく、アクセス制御(web.xml)の記入について説明します。
※生のxmlを書くわけではなく、NetBeansにおんぶにだっこで設定します。

1 件のコメント:

  1. おはようございます。

    認証方法がしっかりしていれば、安心ですね。

    返信削除