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

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

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

10.2.1 クッキーの取得と登録

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

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

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

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

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

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

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

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

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

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

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

実行結果

アプリケーション構成

① 親フォルダの入力または選択 :web_basic/src/main/webapp/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/src/main/java
② パッケージ :ch10
③ 名前 :UseCookieFormServlet
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :useCookieForm1.jspからの画面遷移でアクセスされる

➢ UseCookieFormServlet.java
package ch10;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/UseCookieFormServlet")
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_basic/src/main/webapp/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回目アクセス)

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

日本語を扱うクッキーのエンコードとデコード

 5章や8章で触れたように、本来、日本語のデータを取り扱う時は、エンコードやデコードについて考慮してソースコードを組み立てる必要があります。クッキーについてもそれは同様で、文字化けを回避するために、登録する時と取得する時の両方に文字エンコーディングを指定する必要がありました。

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

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

 今回スクールが用意した環境構築資源では、上記のメソッドを使う必要はありませんが、実際の業務で扱うプログラムでは登場しているかもしれないので、存在は覚えておいてください。


NEXT>> 10.3 本章のまとめ