第1章 クッキーとセッションを利用しよう

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

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

1.2.1 クッキーの取得と登録

クッキーを利用する場合、jakarta.servlet.http.Cookieクラスのオブジェクトを利用します。

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

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

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

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

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

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

実行結果

アプリケーション構成

■ソースコード
【ファイル名:CookieController.java】
package jp.co.f1.spring.cookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Controller
public class CookieController {
	//セッション使用
	@Autowired
	private HttpSession session;
	/**
	 * 「login」へアクセスがあった場合
	 */
	@GetMapping("/login1")
	public ModelAndView login(ModelAndView mav, HttpServletRequest request) {
		// クッキーをリクエストから取得
		Cookie[] cookies = request.getCookies();
		String inputUser = null;
		String inputPassWord = null;
		// クッキーが存在するか確認
		if(cookies != null) {
			for(Cookie cookie: cookies) {
				// クッキーからユーザー情報の取得
				if("user".equals(cookie.getName())) {
					inputUser = cookie.getValue();
				}
				// クッキーからパスワード情報の取得
				if("pass".equals(cookie.getName())) {
					inputPassWord = cookie.getValue();
				}
				// Viewに渡す変数をModelに格納
				mav.addObject("inputUser", inputUser);
				mav.addObject("inputPassWord", inputPassWord);
			}
		}
		mav.setViewName("login1");
		// ModelとView情報を返す
		return mav;
	}
	/*
	 * 「login」へPOST送信された場合
	 */
	@PostMapping("/login1")
	public ModelAndView loginPost(@ModelAttribute @RequestParam String user, @RequestParam String pass, ModelAndView mav, HttpServletResponse response) {
		String preUser = "kandait";
		String prePass = "kandait";
		String msg = "";
		if(user.equals(preUser) && pass.equals(prePass)) {
			Cookie userCookie = new Cookie("user", user);
			userCookie.setMaxAge(60 * 60 * 24 * 1); // 1日(秒)に設定
			response.addCookie(userCookie);
			Cookie passCookie = new Cookie("pass", pass);
			passCookie.setMaxAge(60 * 60 * 24 * 1);
			response.addCookie(passCookie);
			// Viewに渡す変数をModelに格納
			msg = "ログインに成功しました!";
		} else {
			msg = "ログインに失敗しました。";
		}
		// Viewに渡す変数をModelに格納
		mav.addObject("msg", msg);
		// 画面に出力するViewを指定
		mav.setViewName("login2");
		// ModelとView情報を返す
		return mav;
	}
}
【ファイル名:login1.html】
<!DOCTYPE html>
<html>

<head>
  <title>クッキーを利用したプログラム</title>
</head>

<body>
  <h1>ログインフォーム</h1>
  <form action="/login1" method="POST">
    <table>
      <tr>
        <th>ユーザー:</th>
        <td>
          <input type="text" id="user" name="user" th:value="${inputUser}">
        </td>
      </tr>
      <tr>
        <th>パスワード:</th>
        <td>
          <input type="password" id="pass" name="pass" th:value="${inputPassWord}">
        </td>
      </tr>
      <td>
        <input type="submit" value="ログイン">
      </td>
    </table>
  </form>
</body>

</html>
【ファイル名:login2.html】
<html>

<head>
  <title>クッキーを利用したプログラム</title>
</head>

<body>
  <form action="/login1">
    <span th:text="${msg}">
    </span>
    <br>
    <input type="submit" th:value="ログインフォームに戻る">
  </form>
</body>

</html>

アプリケーションにアクセス
以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8080/login1

解説

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

それでは、プログラムの解説を行ないます。
このプログラムは、フォームに入力されたデータが正しいユーザーとパスワードだった場合にクッキーに登録し、2回目以降の入力を簡単に行える機能を持ったログイン画面です。
まず、アプリケーションにアクセスすると、CookieControllerの「/login」に対応するloginメソッドが呼び出されます。最初のアクセスはURLを直接指定して行いますのでGET送信されます。

Cookie[] cookies = request.getCookies();

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

1回目のアクセス時に入力フォームからユーザーとパスワード入力することで、メソッド内で正しいユーザーとパスワードを比較します。

正解だった場合は、そのログイン情報をクッキーに登録する準備を行い、ログイン成功メッセージを変数に格納します。

if(user.equals(preUser) && pass.equals(prePass)) {
	Cookie userCookie = new Cookie("user", user);
	userCookie.setMaxAge(60 * 60 * 24 * 5); // 5日(秒)に設定
	response.addCookie(userCookie);
	Cookie passCookie = new Cookie("pass", pass);
	passCookie.setMaxAge(60 * 60 * 24 * 5);
	response.addCookie(passCookie);
	// Viewに渡す変数をModelに格納
	msg = "ログインに成功しました!";

不正解だった場合は、ログイン失敗メッセージを変数に格納します。

} else {
	msg = "ログインに失敗しました。";
}

その後、メッセージを格納した変数とビューの名前をModelに格納し、画面遷移を行います。

mav.addObject("msg", msg);
mav.setViewName("login2");
return mav;

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

72: Cookie userCookie = new Cookie("user", user);
76: Cookie passCookie = new Cookie("pass", pass);

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

73: userCookie.setMaxAge(60 * 60 * 24 * 1);
77: passwordCookie.setMaxAge(60 * 60 * 24 * 1);

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

1回目のログイン後に、クッキーの状態を確認してみましょう。「user」と「pass」の2件のcookieが登録されていることが確認できます。

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

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

2回目以降のアクセス時、loginメソッドでは、取得したCookie配列からfor文とgetName()メソッドを利用してクッキーの名前を比較し、各値を取得しています。この値を各フォームの初期値とすることで入力済みの状態にすることができます。

if(cookies != null) {
	for(Cookie cookie: cookies) {
		// クッキーからユーザー情報の取得
		if("user".equals(cookie.getName())) {
			inputUser = cookie.getValue();
		}
		// クッキーからパスワード情報の取得
		if("pass".equals(cookie.getName())) {
			inputPassWord = cookie.getValue();
		}
		// Viewに渡す変数をModelに格納
		mav.addObject("inputUser", inputUser);
		mav.addObject("inputPassWord", inputPassWord);
	}
}

取得されたクッキー配列をデバッグ画面の変数ビューで確認すると以下の図のようになります。

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

NEXT>> 1.3 セッションを利用したデータの共有