- Home ›
- サーブレット/JSP入門 ›
- ユーザー認証
セッションを使ったカスタム認証
ここまではTomcatで標準で用意されている認証の方法を確認して来ましたが、標準で用意されている方式は簡易に利用できる反面、カスタマイズするにも限界があります。例えばログアウト処理なども行うことが出来ません。
そこでここからは認証を方式を自分で一から構築する方法を試して行きます。今回は次のようにしてみます。
ユーザー名とパスワードはHTMLページ上のフォームを使う ユーザー管理はデータベースを利用する 送られてきたユーザー名とパスワードでデータベースを検索して認証する 認証が通った場合はセッションに記録する 保護されているページではセッションの有無をチェックする ログアウト機能を付ける
少し長くなるので細かく分けて作成してみます。
認証の対象となるサーブレットの作成
まず保護する対象となるサーブレットを作成します。これらのサーブレットにアクセスがあった場合にはユーザー認証が行われているかどうかをチェックし、認証済みならば内容を表示し、認証されていなければログイン画面へ移動します。
認証が行われているかどうかはセッションを使います。セッションの「login」データがあるかどうかをチェックします。
HttpSession session = request.getSession(false); if (session == null){ /* まだ認証されていない */ session = request.getSession(true); response.sendRedirect("/auth/Login"); }else{ Object loginCheck = session.getAttribute("login"); if (loginCheck == null){ /* まだ認証されていない */ response.sendRedirect("/auth/Login"); } }
セッションの有無を確認し、セッションが開始されていなかったりセッション開始されていても「login」に関するデータが無い場合はログイン画面へ移動します。セッションが開始されていない場合もこの画面でセッションを開始します。
またログイン画面に一度飛ばした後で、本来アクセスしたかったURLへ移動してあげる必要がありますので、どのサーブレットに対してアクセスしようとしていたのかを保存しておきます。
リクエストがあったURLを取得するには「HttpServletRequest」インターフェースで定義されている「getRequestURI」メソッドを使います。
getRequestURI public java.lang.String getRequestURI()
Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. The web container does not decode this String. For example: First line of HTTP request Returned Value ----------------------------------------------------- POST /some/path.html HTTP/1.1 /some/path.html GET http://foo.bar/a.html HTTP/1.0 /a.html HEAD /xyz?a=b HTTP/1.1 /xyz To reconstruct an URL with a scheme and host, use HttpUtils.getRequestURL(javax.servlet.http.HttpServletRequest). Returns: a String containing the part of the URL from the protocol name up to the query string
本来アクセスしようとしたURLを取得したらセッションの「target」に保存しておきます。
String target = request.getRequestURL(); session.setAttribute("target", target);
結果的に次のようなサーブレットになります。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class CustomAuth1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ response.setContentType("text/html; charset=Shift_JIS"); PrintWriter out = response.getWriter(); String target = request.getRequestURI(); HttpSession session = request.getSession(false); if (session == null){ /* まだ認証されていない */ session = request.getSession(true); session.setAttribute("target", target); response.sendRedirect("/auth/Login"); }else{ Object loginCheck = session.getAttribute("login"); if (loginCheck == null){ /* まだ認証されていない */ session.setAttribute("target", target); response.sendRedirect("/auth/Login"); } } out.println("<html>"); out.println("<head>"); out.println("<title>ユーザー認証テスト</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>テストページ1</p>"); out.println("<p><a href=\"/auth/CustomAuth2\">テストページ2へ</a></p>"); out.println("</body>"); out.println("</html>"); } }
またほぼ同じ内容のサーブレットをもう1つ作っておきます。この2つのサーブレットはお互いにリンクが張ってあります。
実際に試してみる
ではこの時点でのテストを行っておきます。まだユーザー認証用の「Login」サーブレットがありませんので、暫定的に次のサーブレットを用意します。
本来であればユーザー名とパスワードを入力してもらいユーザー認証を行いますが、取りあえず認証を全て通して本来アクセスするはずのURLへのリンクを設定するだけにしてあります。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Login1 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>"); out.println("<p>本来はここでログインするためのフォームが表示されます</p>"); HttpSession session = request.getSession(false); if (session == null){ /* セッションが開始されずにここへ来た場合は無条件でエラー表示 */ out.println("<p>不正なアクセスです</p>"); }else{ /* 今回は無条件で認証を許可する */ out.println("<p>認証が行われました</p>"); /* 認証済みにセット */ session.setAttribute("login", "OK"); /* 本来のアクセス先へのリンクを設定 */ String target = (String)session.getAttribute("target"); out.println("<a href=\"" + target + "\">ページを表示する</a>"); } out.println("</body>"); out.println("</html>"); } }
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>Login1</servlet-class> </servlet> <servlet-mapping> <servlet-name>Login</servlet-name> <url-pattern>/Login</url-pattern> </servlet-mapping> </web-app>
それでは一度サーブレットを再起動してから、ブラウザで「http://localhost:8080/auth/CustomAuth1」へアクセスして下さい。
「CustomAuth1」サーブレットへアクセスしてもセッションに必要な情報が保存されていませんので「Login」サーブレットへリダイレクトされます。今回はテスト用なのでこの時点で認証が行われていますので、「ページを表示する 」をクリックすれば本来アクセスするはずの「CustomAuth1」サーブレットへアクセスします。
今度はセッションが既に開始されていて、必要な情報がセッションに登録されているので「CustomAuth1」サーブレットの中身が表示されます。
また「CustomAuth1」サーブレットからリンクが張ってある「CustomAuth2」サーブレットにも認証のチェックが入っていますが、既に認証済みですのでリンクをクリックすれば普通に表示されます。
それでは次のページでログイン画面の部分を作成します。
( Written by Tatsuo Ikura )
著者 / TATSUO IKURA
これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。