クッキーを利用してみよう

10.2 クッキーを利用してみよう

 本節では、クライアント側にデータを保管し、JSP/サーブレットで利用するクッキーの使い方について学習していきます。

10.2.1 クッキーの取得と登録

 クッキーを利用する場合、javax.servlet.http.Cookieクラスのオブジェクトを利用します。
 新しくクッキーを作成する場合は、new演算子を利用し、Cookieクラスのオブジェクトを生成します。オブジェクトの生成を行う際に、引数としてデータの名前と登録するデータを渡します。また、クッキーには個別に有効期限を指定する必要があるため、setMaxAge()メソッドを利用し有効期限を秒単位で設定します。

書式:Cookieオブジェクトの生成

デフォルトのクッキーの有効期限

 デフォルトのクッキーの有効期間は、ブラウザを終了するまでになっています。そのため、有効期限を指定しないと、ブラウザを閉じると同時にデータが削除されます。クライアント側にデータを保存するためには、有効期限の設定を忘れずに行いましょう。また、有効期限を0に指定した場合、登録と同時にクッキーが削除されることになるので、任意のクッキーを削除したい場合に0を設定するといった使い方も可能です。

 リクエストとともに送信されたクッキーを取得する場合には、HttpServletRequestインタフェースに定義された以下のメソッドを利用します。複数のクッキーが存在した場合、1つ1つのクッキーを個別に取得するのではなく、全てのクッキーを配列として取得することになります。

書式:Cookieオブジェクトの取得

 クッキーをクライアントに登録する場合は、まず、クッキーをレスポンスに登録し、レスポンスの情報とともにクライアントに送信する手順が必要です。クッキーをレスポンスに登録する場合は、responseオブジェクトに用意されたaddCookie()メソッドを利用します。メソッドの引数にはCookieクラスのオブジェクトを渡します。

書式:Cookieオブジェクトの登録

 では、クッキーを利用するプログラムを作成してみましょう

クッキーを利用したプログラム

 クッキーを利用して、ログインを自動化するプログラムです。1回目のアクセス時は入力フォームは空の状態でデータを入力します。2回目以降はクッキーから取得された値が自動で入力フォームに入力されます。クッキーのデータがどのように登録されているかを確認してみましょう。

実行結果

アプリケーション構成

① 親フォルダの入力または選択 :web_basic/view/ch10
② ファイル名 :useCookieForm1.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch10/useCookieForm1.jsp

➢ useCookieForm1.jsp
<%@page contentType="text/html; charset=UTF-8" %>

<%
String user = "";		//ユーザーを管理する変数
String pass = "";		//パスワードを管理する変数

Cookie[] userCookie = request.getCookies();		//クッキーの取得
String error = (String)request.getAttribute("error");	//エラーメッセージの取得

 //クッキーがあるか判定
 if(userCookie != null){
 	for(int i = 0 ; i < userCookie.length; i++){
 		//クッキーからユーザー情報の取得
 		if(userCookie[i].getName().equals("user")){
 			user = userCookie[i].getValue();
 		}
 		//クッキーからパスワード情報の取得
 		if(userCookie[i].getName().equals("pass")){
 			pass = userCookie[i].getValue();
 		}
 	}
 }
 //エラーメッセージがない(null)場合の代入処理
 if(error == null){
 	error = "";
 }
 %>
 
 <html>
 	<head>
 		<title>クッキーを利用したプログラム</title>
 	</head>
 	<body>
 		<form action="<%=request.getContextPath() %>/UseCookieFormServlet" method="post">
 			<table>
 				<tr>
 					<th>ユーザー</th>
 					<td><input type="text" name="user" value=<%= user %>></td>
 				</tr>
 				<tr>
 					<th>パスワード</th>
 					<td><input type="password" name="password" value=<%= pass %>></td>
 				</tr>
 			</table>
 			<table>
 				<tr>
 					<td><input type="submit" value="ログイン"></td>
 				</tr>
 			</table>
 		</form>
 		<%= error %>
     </body>
 </html>	

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch10
③ 名前 :UseCookieFormServlet
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :useCookieForm1.jspからの画面遷移でアクセスされる

➢ UseCookieFormServlet.java
package ch10;

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

public class UseCookieFormServlet extends HttpServlet {
	public void doPost(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
 
 		String error = "";	//エラーメッセージ用変数
 		String user = "kanda";	//ユーザー
 		String pass = "kanda";	//パスワード
 		String inputUser = request.getParameter("user");	//入力パラメータの取得
 		String inputPass = request.getParameter("password");	//入力パラメータの取得
 
 		//ログイン処理
 		if(!inputUser.equals(user) || !inputPass.equals(pass)){
 			error = "ログイン失敗!";
 			request.setAttribute("error", error);
 			request.getRequestDispatcher("/view/ch10/useCookieForm1.jsp").forward(request, response);
 		}else{
 			//ユーザー用クッキーの生成
 			Cookie userCookie = new Cookie("user", user);
 			userCookie.setMaxAge(60 * 60 * 24 * 1);
 			response.addCookie(userCookie);
 
 			//パスワード用クッキーの生成
 			Cookie passwordCookie = new Cookie("pass", pass);
 			passwordCookie.setMaxAge(60 * 60 * 24 * 1);
 			response.addCookie(passwordCookie);
 
 			request.getRequestDispatcher("/view/ch10/useCookieForm2.jsp").forward(request, response);
 		}
 	}
 }
➢ web.xml
<servlet>
	<servlet-name>UseCookieFormServletMapping</servlet-name>
	<servlet-class>ch10.UseCookieFormServlet</servlet-class>
</servlet> 
<servlet-mapping>
	<servlet-name>UseCookieFormServletMapping</servlet-name>
	<url-pattern>/UseCookieFormServlet</url-pattern>
</servlet-mapping>

① 親フォルダの入力または選択 :web_basic/view/ch10
② ファイル名 :useCookieForm2.jsp
③ アクセスURL :UseCookieFormServletjavaからの画面遷移でアクセスされる

➢ useCookieForm2.jsp
<%@page contentType= "text/html; charset=UTF-8" %>
<html>
	<head>
		<title>クッキーを利用したプログラム</title>
	</head>
	<body>
		ログインしました。
	</body>
</html>

解説
 プログラムの解説をはじめる前に、プログラムにアクセスする前のクッキーの状態をブラウザから確認します。これまでの学習ではクッキーを利用したプログラムを作成していないので、localhostのサイト名のクッキーは登録されていません。

図 10.2.1:ブラウザでのクッキーの確認(アクセス前)

 それでは、プログラムの解説を行ないます。
 このプログラムは、フォームに入力されたデータが正しいユーザとパスワードだった場合にクッキーに登録し、2回目以降の入力を簡単に行える機能を持ったログイン画面です。
 入力フォームであるuseCookieForm1.jspでは、まず始めにクッキーのデータを取得します。
   7:Cookie[] userCookie = request.getCookies();

 クッキーが存在する場合は、配列としてデータを取得し利用することができますが、1回目のアクセス時にはユーザーとパスワードはクッキーに登録されていないため、値は取得されません。そのため、入力フォームは空白で表示されます。

図 10.2.2:入力フォームの初期画面(1回目アクセス)

 1回目のアクセス時に入力フォームからユーザとパスワード入力することで、サーブレット内で正しいユーザとパスワードを比較します。不正解だった場合は、エラーメッセージをリクエストに登録し入力フォームへ戻ります。
   18:if(!inputUser.equals(user) || !inputPass.equals(pass)){
   19: error = "ログイン失敗!";
   20: request.setAttribute("error", error);
   21: request.getRequestDispatcher("/view/ch10/useCookieForm1.jsp").forward(request, response);

 正解だった場合は、そのログイン情報をクッキーに登録する準備を行い、ログイン後の画面へフォワードします。
   22:}else{
   23: //ユーザー用クッキーの生成    24: Cookie userCookie = new Cookie("user", user);
   25: userCookie.setMaxAge(60 * 60 * 24 * 1);
   26: response.addCookie(userCookie);
   27:
   28: //パスワード用クッキーの生成
   29: Cookie passwordCookie = new Cookie("pass", pass);
   30: passwordCookie.setMaxAge(60 * 60 * 24 * 1);
   31: response.addCookie(passwordCookie);
   32:
   33: request.getRequestDispatcher("/view/ch10/useCookieForm2.jsp").forward(request, response);
   34:}

 クッキーに登録するデータが複数ある場合は、各々のCookieオブジェクトが必要です。このプログラムではユーザーとパスワードの2つのデータを登録するため、Cookieオブジェクトを2つ生成しています。
   24: Cookie userCookie = new Cookie("user", user);
   29: Cookie passwordCookie = new Cookie("pass", pass);

 各々のクッキーには有効期限を設定します。このプログラムでは有効期限を1日に設定しています。引数は秒単位で設定し、有効期限が1日の場合は86400秒と書いても構いませんが、有効期限が分かりやすくなるように「60秒*60分*24時間*1日」という形で記述するのが一般的です。
   25: userCookie.setMaxAge(60 * 60 * 24 * 1);
   30: passwordCookie.setMaxAge(60 * 60 * 24 * 1);

 クッキーに登録する最後の手順として、レスポンスへの登録を行います。これによりレスポンスがブラウザに送られる際にクッキーの情報もあわせて送られ、パソコン内に保存されることになります。
   26: response.addCookie(userCookie);
   31: response.addCookie(passwordCookie);

 UseCookieFormServlet.javaからuseCookieForm2.jspにフォワードし、useCookieForm2.jspの画面が表示されるとクッキーに「user」と「pass」が登録されていることが確認できます。なお、「user」と「pass」の他に「JSESSIONID」という名前のクッキーも登録されていますが、こちらについては12章で学習することになります。

図 10.2.3:ログイン後のクッキーの確認

 1回目のアクセス時には、ログイン後の画面が表示されると、パスワードの保存の確認が表示される場合があります。この表示はクッキーの登録の確認ではなく、ブラウザ独自の機能で、パスワードを保存するかどうかの確認です。ここでは表示の一番右にある「×」ボタンをクリックしておきましょう。以下の画面はGoogle Chromeでのパスワードの保存確認の表示です。ブラウザごとに異なりますのでご注意ください。

図 10.2.4:パスワードの保存確認

 1回目のアクセスが完了したら、一旦ブラウザを閉じて、再度入力フォームへアクセスしてみましょう。すると2回目のアクセス時には、ユーザーとパスワードが入力された状態の入力フォームが開かれます。

図 10.2.5:クッキー情報を取得した入力フォーム

 2回目以降のアクセス時、useCookieForm1.jspでは、取得したCookie配列からfor文とgetName()メソッドを利用してクッキーの名前を比較し、各値を取得しています。この値を各フォームの初期値とすることで入力済みの状態にすることができます。
   11:if(userCookie != null){
   12: for(int i = 0 ; i < userCookie.length; i++){
   13: //クッキーからユーザー情報の取得
   14: if(userCookie[i].getName().equals("user")){
   15: user = userCookie[i].getValue();
   16: }
   17: //クッキーからパスワード情報の取得
   18: if(userCookie[i].getName().equals("pass")){
   19: pass = userCookie[i].getValue();
   20: }
   21: }
   22:}

 なお、本章ではまだJSP/サーブレットのデバッグについて学習していないので、図のみでの紹介となりますが、取得されたクッキー配列をデバッグ画面の変数ビューで確認すると以下の図のようになります。

図 10.2.6:変数ビューでのクッキーの確認(2回目アクセス)

 このように、クッキーを利用すると、入力されたデータをパソコン側に保存し、次回のアクセス時に利用することが可能になります。

10.2.2 クッキーに日本語を登録する

 パソコン内に登録されたクッキーの情報は、リクエストとともにプログラムに送られます。また、プログラム内で生成されたCookieオブジェクトは、レスポンスの情報とともにブラウザに送られます。そのため、リクエストやレスポンスに日本語を含めるときと同じように、クッキーに日本語を登録する場合にもエンコードとデコードの設定が必要です。

書式:クッキーに登録するデータのエンコード

 データのエンコードはURLEncoder.encode()メソッドを利用し、Cookieオブジェクトの生成前に行います。上記の凡例では「ユーザー」という名前で「神田タロー」という値を登録しています。encode()メソッドの引数にエンコードする文字列と文字エンコーディングを渡し、名前とデータをエンコードしています。

書式:クッキーから取得したデータのデコード

 getName()メソッドで取得した名前をURLDecoder.decode()メソッドを利用し、デコードします。デコードされた名前を取得したいデータの名前と比較し、合っていた場合はgetValue()メソッドを利用してデータを取得します。取得したデータも名前と同じようにURLDecoder.decode()メソッドを利用してデコードを行います。
 上記の凡例では「ユーザー」という名前で登録されたデータを取得しています。

クッキーに日本語を登録するプログラム

 前項で作成したログインプログラムのユーザを、日本語で登録できるように変更します。日本語を登録する際に行うエンコードとデコードの処理について確認しましょう。なお、ログイン後の画面については、useCookieForm2.jspをそのまま利用します。

実行結果

アプリケーション構成

① 親フォルダの入力または選択 :web_basic/view/ch10
② ファイル名 :useCookieForm3.jsp
③ アクセスURL :http://localhost:8080/web_basic/view/ch10/useCookieForm3.jsp

➢ useCookieForm3.jsp
<%@page contentType="text/html; charset=UTF-8" %>
<%@page import="java.net.*" %>

<%
String user = "";		//ユーザーを管理する変数
String pass = "";		//パスワードを管理する変数

Cookie[] userCookie = request.getCookies();		//クッキーの取得
String error = (String)request.getAttribute("error");	//エラーメッセージの取得
 
 //クッキーがあるか判定
 if(userCookie != null){
 	for(int i = 0 ; i < userCookie.length; i++){
 		//クッキーからユーザー情報の取得
 		if(userCookie[i].getName().equals("user")){
 			user = URLDecoder.decode(userCookie[i].getValue(), "UTF-8");
 		}
 		//クッキーからパスワード情報の取得
 		if(userCookie[i].getName().equals("pass")){
 			pass = userCookie[i].getValue();
 		}
 	}
 }
 //エラーメッセージがない(null)場合の代入処理
 if(error == null){
 	error = "";
 }
 %>
 
 <html>
 	<head>
 		<title>クッキーを利用したプログラム</title>
 	</head>
 	<body>
 		<form action="<%=request.getContextPath() %>/UseCookieFormServlet2" method="post">
 			<table>
 				<tr>
 					<th>ユーザー</th>
 					<td><input type="text" name="user" value=<%= user %>></td>
 				</tr>
 				<tr>
 					<th>パスワード</th>
 					<td><input type="password" name="password" value=<%= pass %>></td>
 				</tr>
 			</table>
 			<table>
 				<tr>
 					<td><input type="submit" value="ログイン"></td>
 				</tr>
 			</table>
 		</form>
 		<%= error %>
     </body>
 </html>

① ソース・フォルダ :web_basic/WEB-INF/src
② パッケージ :ch10
③ 名前 :UseCookieFormServlet2
④ スーパークラス :javax.servlet.http.HttpServlet
⑤ アクセスURL :useCookieForm3.jspからの画面遷移でアクセスされる

➢ UseCookieFormServlet2.java
package ch10;

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

public class UseCookieFormServlet2 extends HttpServlet {

 	public void doPost(HttpServletRequest request, HttpServletResponse response)
 	throws ServletException, IOException {
 
 		request.setCharacterEncoding("UTF-8");
 
 		String error = "";	//エラーメッセージ用変数
 		String user = "神田タロー";	//ユーザー
 		String pass = "kanda";		//パスワード
 		String inputUser = request.getParameter("user");	//入力パラメータの取得
 		String inputPass = request.getParameter("password");	//入力パラメータの取得
 
 		//ログイン処理
 		if(!inputUser.equals(user) || !inputPass.equals(pass)){
 			error = "ログイン失敗!";
 			request.setAttribute("error", error);
 			request.getRequestDispatcher("/view/ch10/useCookieForm3.jsp").forward(request, response);
 		}else{
 			//ユーザー用クッキーの生成
 			user = URLEncoder.encode(user, "UTF-8");
 			Cookie userCookie = new Cookie("user", user);
 			userCookie.setMaxAge(60 * 60 * 24 * 1);
 			response.addCookie(userCookie);
 
 			//パスワード用クッキーの生成
 			Cookie passwordCookie = new Cookie("pass", pass);
 			passwordCookie.setMaxAge(60 * 60 * 24 * 1);
 			response.addCookie(passwordCookie);
 
 			request.getRequestDispatcher("/view/ch10/useCookieForm2.jsp").forward(request, response);
 		}
 	}
 }
➢ web.xml
<servlet>
	<servlet-name>UseCookieFormServlet2Mapping</servlet-name>
	<servlet-class>ch10.UseCookieFormServlet2</servlet-class>
</servlet> 
<servlet-mapping>
	<servlet-name>UseCookieFormServlet2Mapping</servlet-name>
	<url-pattern>/UseCookieFormServlet2</url-pattern>
</servlet-mapping>

解説
 このプログラムでは、ログイン可能なユーザ名を「kanda」から「神田タロー」に変更しています。また、日本語を扱うためにエンコード及びデコードの処理を追加しています。クッキーに日本語のユーザ情報を保存することで、2回目以降のログイン時にユーザとパスワードが入力済みの状態になります。

図 10.2.7:クッキー情報を取得した入力フォーム

 前項で作成したプログラムと大きく違う点は、クッキーを取得した際のデコードの処理と、Cookieオブジェクトを生成する際のエンコードの処理です。まずはデコードの処理を見てみましょう。

 useCookieForm3.jspでは、2行目でインポート宣言を追加しています。クッキーのデコードやエンコードで利用するクラスはjava.netパッケージに存在するクラスです。
   2:<%@page import="java.net.*" %>

 取得したクッキーの値をデコードする処理は14行目で行われています。
 16行目ではgetValue ()メソッドを使い、Cookieオブジェクトに保存されたデータを取得します。取得したデータに対してURLDecoder.decode()メソッドを利用して UTF-8という文字コードでデコード処理を行なっています。
   15: if(userCookie[i].getName().equals("user")){
   16: user = URLDecoder.decode(userCookie[i].getValue(), "UTF-8");
   17: }

 次にエンコードの処理について確認してみましょう。
  エンコードの処理は、UseCookieFormServlet2.javaの28行目で行われています。変数userに格納された「神田タロー」という文字列を、URLEncoder.encode()メソッドを利用してUTF-8という文字コードでエンコードしています。その後、エンコードされたデータをCookieオブジェクトに登録することで、クッキーで日本語を扱うことが可能になります。
   28: user = URLEncoder.encode(user, "UTF-8");

 このように、クッキーで日本語を扱う場合は、レスポンスへ保存する前に文字列のエンコードを行い、リクエストから取得した後にデコードを行います。クッキーで日本語を扱う機会はそう多くはありませんが、難しい手順ではありませんので覚えおきましょう。


NEXT>> 10.3 本章のまとめ