クッキーとは
Webアプリケーションには、ユーザーPC(クライアント)へデータを保持できる仕組み「クッキー(cookie)」が用意されています。保存可能なデータは小さなテキスト形式です。
クッキーの主な目的の 1 つは、時間を節約するための便利な機能を提供することです。
クッキーにログイン情報などを保管することで、次回のアクセスからログイン処理を省略することができるようになります。
クッキーには以下の特徴があります。
・登録した情報以外の情報にはアクセスできない
・ ブラウザごとに、サーバ(ドメイン)ごとに管理される。
・1つのクッキーには4096バイトのデータを登録できる。
・ 最大で300個のクッキーをパソコン内に保存することができる。
・1つのWebアプリケーションから同じパソコンに対して登録できる数は20個に制限されている。
・各クッキーには有効期限を設定することができ、有効期限を過ぎたクッキーは消滅する。
・ブラウザの設定でクッキーを利用不可にすることができる。
・セキュリティ上の危険性が存在する。
これらの特徴(制約)があり、一時的なデータを管理するのには便利な「セッション」があるので、
クッキーを直接扱う機会はそれほど多くはありません。
しかし、ログインの自動化や一時データを長期に保管するといった機能を
アプリケーションに実装する場合にクッキーは大変便利な仕組みとなっています。
クッキーの情報は、ブラウザの機能を使えば、どのようなデータが登録されているのかを確認することができます。
また、通信の途中で盗聴される可能性もゼロではありません。
そのためクッキーにIDやパスワード、個人情報など重要な情報を登録する場合は、セキュリティを考慮した仕組みが別途必要になります。
クッキーを使用したWebアプリケーションへアクセスすると、
そのWebアプリケーション専用のファイルがパソコン内に保存されます。
また、保存されたデータは、再度同じWebアプリケーションにアクセスした際に、
ブラウザからWebアプリケーションに自動的に送られる仕組みになっています。
クッキーはクライアント(ユーザーのブラウザ)の一部として、ユーザーのローカル環境に保存されます。
具体的には、ブラウザがクッキーをファイルまたはメモリ内の特定の場所に保存します。
クッキーの確認方法
保存されたクッキーはブラウザから確認することができます。
「Google Chrome」であれば以下の手順で確認が出来ます。
1.画面右上の三点リーダーをクリックし、「設定」を選択

2.プライバシーとセキュリティの「サードパーティ Cookie」を選択

3.「詳細設定」の「すべてのCookieとサイトデータを表示」を選択

すると、Cookieやサイトデータを保存しているサイトの一覧を見ることができます。
クッキーの取得と登録
クッキーを利用する場合、jakarta.servlet.http.Cookieクラスのオブジェクトを利用します。
新しくクッキーを作成する場合は、new演算子を利用し、Cookieクラスのオブジェクトを生成します。
オブジェクトの生成を行う際に、引数としてデータの名前と登録するデータを渡します。
また、クッキーには個別に有効期限を指定する必要があるため、
setMaxAge()メソッドを利用し有効期限を秒単位で設定します。
書式は以下の通りとなります。
Cookie cookie = new Cookie("データの名前",登録するデータ);
cookie.setMaxAge(有効期限);
なお、デフォルトではクッキーの有効期限はブラウザが終了するまでとなっているため、
有効期限を設定しないと、ブラウザを閉じると同時にデータが削除されます。
クライアント側にデータを保存するために、有効期限の設定を忘れずに行いましょう!
なお、有効期限を0に指定した場合、登録と同時にクッキーが削除されることになるので、
任意のクッキーを削除したい場合に0を設定するといった使い方も可能です。
リクエストとともに送信されたクッキーを取得する場合には、HttpServletRequestインタフェースに定義された以下のメソッドを利用します。
複数のクッキーが存在した場合、1つ1つのクッキーを個別に取得するのではなく、
全てのクッキーを配列として取得することになります。
Cookie[] cookies = request.getCookies();
クッキーをクライアントに登録する場合は、まず、クッキーをレスポンスに登録し、
レスポンスの情報とともにクライアントに送信する手順が必要です。
クッキーをレスポンスに登録する場合は、responseオブジェクトに用意されたaddCookie()メソッドを利用します。メソッドの引数にはCookieクラスのオブジェクトを渡します。
response.addCookie(cookie);
クッキーを利用したプログラム
「com.cmps.spring.controller」パッケージ内に「CookieSeesionController.java」を用意し
以下のソースを記述しましょう。
・CookieSeesionController.java
@Controller
@RequestMapping("/cookie")
public class CookieSeesionController {
/**
* ログイン画面を表示する
* 「/login」へアクセスがあった場合
*/
@GetMapping("/login")
public String login(Model model,
@CookieValue(name = "name", required = false) String nameCookie,
@CookieValue(name = "pass",required = false) String passCookie) {
// 取得したCookieをModel情報に登録
model.addAttribute("name",nameCookie);
model.addAttribute("pass",passCookie);
// 画面に出力するViewを指定
return "cookieSession/login";
}
/**
* ログイン処理をする
*/
@PostMapping("/result")
public String loginPost(Model model,
@RequestParam(required=false) String name,
@RequestParam(required=false) String pass,
HttpServletResponse response) {
// クッキーを作成し、レスポンスに追加
Cookie nameCookie = new Cookie("name",name);
Cookie passCookie = new Cookie("pass",pass);
nameCookie.setMaxAge(60 * 60); // 1時間有効
passCookie.setMaxAge(60 * 60);
response.addCookie(nameCookie);
response.addCookie(passCookie);
// モデルにデータを登録
model.addAttribute("name",name);
model.addAttribute("pass",pass);
// 画面に出力するViewを指定
return "cookieSession/result" ;
}
}
次に表示するためのviewを用意します。
「src/main/resources/templates」配下に「cookieSession」フォルダを作成し、
その中に「login.html」「result.html」を配置しましょう。
・login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
<meta charset="UTF-8">
<title>クッキーを用いたプログラム</title>
</head>
<body>
<form method="post" th:action="@{/cookie/result}" accept-charset="UTF-8">
<ul>
<li>
<h2>ユーザー名</h2>
<input type="text" name="name" th:value="${name}">
</li>
<li>
<h2>パスワード</h2>
<input type="password" name="pass" th:value="${pass}">
</li>
</ul>
<input type="submit" value="ログイン">
</form>
</body>
</html>
・result.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
<meta charset="UTF-8">
<title>クッキーの情報を表示</title>
</head>
<body>
<ul>
<li>
<h2>ユーザー名</h2>
<p th:text="${name}"></p>
</li>
<li>
<h2>パスワード</h2>
<p th:text="${pass}"></p>
</li>
</ul>
</body>
</html>
ログインボタンを押すと、次のページに入力値が表示されます。
loginPostメソッド内でそれぞれの入力値をクッキーに保存していますので
再度loginページにアクセスすると、クッキーから取得した値をテキストボックスに表示するようになっています。
loginメソッドではCookieValueアノテーションを使用し、
ブラウザに保存されているnameとpassのクッキー情報を取得しています。
@CookieValue(name = "name", required = false) String nameCookie
@CookieValue(name = "pass",required = false) String passCookie
引数内の「required = false」ですが、
クッキーが取得できない場合の実行時エラーを回避するために記述しています(デフォルトではtrue)。
なお、リクエストに Cookie が存在しない場合は null 値が返されます。
loginPostメソッドでは、フォームから送信された name と pass を取得し、
クッキーを 作成 し、レスポンスに追加しています。
Cookie nameCookie = new Cookie("name",name);
nameCookie.setMaxAge(60 * 60);
setMaxAge()メソッドの引数「60*60」は、「60秒×60 = 3600秒(一時間)」を意味します。
セッション(Session)とは
セッション(Session)とは、複数のユーザがアクセスするWebアプリケーションで、各ユーザの状態の保存・ユーザの区別を行う機能で、ユーザの識別はセッションIDを使って行います。
複数のリクエスト・レスポンスにまたがってユーザーの識別とデータの管理をする仕組みです。
セッションはクライアント毎に作成され、セッションが開始されるとセッションを
識別するためのセッションIDをクライアントへ保存し、保存したい値をセッション変数としてサーバ側に保存します。
クライアントに保存されるセッションIDは、クッキーを利用して保存されます。
また、Javaの場合セッションIDは自動でユニークな値(絶対に被らない値)を生成してくれます。
クッキーはサーバーから命令されることでユーザーのブラウザに保存されます。
それに対し、セッションはサーバー側にデータを一時的に保存するために使います。
HttpSession
HttpSessionインタフェースというAPIを使用することでセッションを簡単に操作できます。
HttpSessionインタフェース引数を与えることで保存、取得、削除などが実行できる、いわばメソッドの集合体です。
Controllerでインジェクト(オブジェクトグラフから取得したインスタンスを注入すること)することで、
HttpSessionを直接使用することが可能です。
@Autowired
HttpSession session;
セッションのデータの登録・取得
セッションにデータを登録する場合、上記で示したインジェクトする方法の他に
セッションオブジェクトを生成する方法もあります。
HttpSession session = request.getSession();
HttpServletRequestインタフェースに定義されたgetSession()メソッドを利用し、HttpSessionオブジェクトを取得します。
セッションへの登録の書式は以下の通りです。
session.setAttribute("データの名前",登録するデータ);
HttpSessionインタフェースのオブジェクトに用意されたsetAttribute()メソッドを利用することで、
セッションへデータを登録することができます。
メソッドの引数には、登録するデータとそのデータにつける名前を渡します。
セッションからのデータ取得は以下の書式にて実行できます。
登録前のデータの型 変数名 = (登録前のデータの型)session.getAttribute("データの名前");
HttpSessionインタフェースのオブジェクトに用意されたgetAttribute()メソッドを利用することで、
セッションに登録されたデータを取得することができます。
メソッドの引数には、登録されたオブジェクトの名前を渡します。
リクエストスコープと同じように、登録されたデータはObject型となるため、セッションから取得したデータは登録する前の型でキャストを行う必要があります。
セッションを用いたプログラミング
requestからセッションへデータを保存し、そのデータをview上に表示するプログラミングです。
「com.cmps.spring.controller」パッケージ内に「SessionController.java」を用意し
以下のソースを記述しましょう。
@Controller
@RequestMapping("/session")
public class SessionController {
// HttpSessionをインスタンス化
@Autowired
private HttpSession session;
/**
* 初期表示ページ 商品をカートへ追加するフォーム
*
* @param model
* @return String View
*/
@GetMapping("/shop")
public String insertIntoCart(Model model) {
// 画面に出力するViewを指定
return "cookieSession/shop";
}
/**
* カートに登録する処理
*
* @param model Model
* @param book String 本の入力値
* @param cd String CDの入力値
* @return String Redirect
*/
@PostMapping("/check")
public String saveCart(Model model, @RequestParam(required = false) String book,
@RequestParam(required = false) String cd) {
// セッションからリストを取得
List<String> bookList = (LinkedList<String>) session.getAttribute("bookList");
List<String> cdList = (LinkedList<String>) session.getAttribute("cdList");
// リストを取得できなければ新規で用意
if (bookList == null || bookList.isEmpty()) {
bookList = new LinkedList<String>();
}
if (cdList == null || cdList.isEmpty()) {
cdList = new LinkedList<String>();
}
// リストにデータを追加
bookList.add(book);
cdList.add(cd);
// セッションへリストを保存
session.setAttribute("bookList", bookList);
session.setAttribute("cdList", cdList);
// showCartへリダイレクト
return "redirect:/session/showCart";
}
/**
* カート内容確認画面を表示する処理
*
* @param model Model
* @return String View
*/
@GetMapping("/showCart")
public String showCart(Model model) {
// セッションからリストを取得
List<String> bookList = (LinkedList<String>) session.getAttribute("bookList");
List<String> cdList = (LinkedList<String>) session.getAttribute("cdList");
// Model に追加
model.addAttribute("bookList", bookList);
model.addAttribute("cdList", cdList);
return "cookieSession/showCart";
}
}
session.getAttribute()で取得してキャストした行について、「未検査のキャスト」といった注釈の下線が出ると思いますが、ここでは想定通りの値のみを返却されるのでキャストして問題ないと考えて未処置としています。
次に表示するためのviewを用意します。
「cookieSession」フォルダ内に「shop.html」「showCart.html」を配置しましょう。
・shop.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
<meta charset="UTF-8">
<title>セッションを用いたプログラム</title>
</head>
<body>
<h2>カートへの追加フォーム</h2>
<form method="post" th:action="@{/session/check}" accept-charset="UTF-8">
<ul>
<li>
<p>本</p>
<input type="text" name="book">
</li>
<li>
<p>cd</p>
<input type="text" name="cd">
</li>
</ul>
<input type="submit" value="購入へ進む">
</form>
<p><a th:href="@{/session/showCart}">[カートを確認]</a></p>
</body>
</html>
・showCart.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
<head>
<meta charset="UTF-8">
<title>セッションを用いたプログラム 送信先</title>
</head>
<body>
<h2>カート内容の表示</h2>
<ul>
<li>
<h2>書籍名</h2>
<p th:each="book : ${bookList}"><span th:text="${book}"></span></p>
</li>
<li>
<h2>タイトル</h2>
<p th:each="cd : ${cdList}"><span th:text="${cd}"></span></p>
</li>
</ul>
<p><a th:href="@{/session/shop}">← [カート追加画面へ]</a></p>
</body>
</html>
初期表示ページからにアクセスして送信すると、書籍名とCDタイトルが追加されていくのが確認できるのではないでしょうか。
insertIntoCartメソッドは、入力画面を表示するためのものなので解説は省きます。
saveCartメソッドでは、getAttribute()メソッドで登録したリストを取得しています。さらにsetAttribute()メソッドを用いてリストをセッションへ保存しています。
// セッションからリストを取得
List<String> bookList = (LinkedList<String>) session.getAttribute("bookList");
List<String> cdList = (LinkedList<String>) session.getAttribute("cdList");
// セッションへデータを保存
session.setAttribute("bookList",bookList);
session.setAttribute("cdList",cdList);
showCartメソッドでも、getAttribute()メソッドで登録したリストを取得しています。
// セッションからデータを取得
List<String> bookList = (LinkedList<String>) session.getAttribute("bookList");
List<String> cdList = (LinkedList<String>) session.getAttribute("cdList");
このようにJavaでは、クッキーやセッションを保存や取得など操作することが出来ます。
