前回は、フォームからデータをサーブレットに渡すところまでをやりました。
今回は、今までの知識を応用してログイン処理を作ってみます。
前回学んだリクエスト属性を使えば、入力画面に入力した内容をもとにJSPの出力画面に情報を表示できました。しかし、実はリクエスト属性は複数ページを跨いで情報の保持ができません。ステートレスといって1対のリクエストとレスポンスで終了してしまうのです。
そこで必要となるのがセッション属性です。セッション属性を使うことで複数ページを跨いで情報の保持ができます。そしてログイン処理は複数ページを跨いで情報を保持する必要のある典型的な処理です。この章ではそんなセッション属性の特徴をログイン処理を実装することにより体験的に学びます。
1. ログイン処理とは
まずは一般的なログイン処理についてまとめておきましょう。皆さんも是非、普段お使いのWebアプリケーションで実験してみてください。(あるいは講師の実演をご覧ください)
突然ですがログインに関する質問です。
- ①一般にWebシステムにログインするにはどのような情報が必要ですか?
あなたの答え: |
- ②ログイン前と後では何が違いますか?
あなたの答え: |
- ③あるブラウザでログイン中に同じブラウザで他のタブを開いたら新しい方のタブでログインは継続されますか?
あなたの答え: |
- ④あるブラウザ(例えばクローム)でログイン中に新しいブラウザ(例えばエッジ)を起動したら新しいブラウザでログインは継続されますか?
あなたの答え: |
- ⑤どんなときにWebアプリからログアウトしますか?
あなたの答え: |
- ⑥ログアウトしてからブラウザの戻るボタンを押すと元のログイン状態に戻りますか?
あなたの答え: |
上記の実験からも明らかなように一般的にはログインとは以下のような処理を指します。
①ユーザーはブラウザからIDとパスワードといった自分だけが知る情報を使ってログインする
②ログイン後はそのユーザーだけが見られるページに遷移できるようになる
③ログイン中は同じブラウザで他のタブを開いてもログインされたままである
④しかし、同じユーザーが別のブラウザで同じページにアクセスしても再度ログイン処理が必要である
⑤ログアウト処理をする、ブラウザを終了するまたは一定時間(大抵は30分間だが銀行のように5分程度と短い場合も)が経過するとログアウトする
⑥ログアウトしてからブラウザの戻るボタンを押すと元のログイン状態に戻らないセキュリティを強化したサイトが存在する
上記結果④から考えるとログイン処理はブラウザごとに固有の情報を利用していると推測できます。
また、結果⑤から考えるとログアウトのタイミングは技術者が個々に設定していることが分かります。
本章では、ログイン処理を実現するにはセッションという仕組みを理解することが必要になるということ、さらに同一セッションで有効なセッション属性を使うことでリクエスト属性では実現できなかった複数リクエストを跨いだデータ保持が可能になるということを解説していきたいと思います。例えば、オンラインショッピングで買い物かごの仕組みが実現できるのは、かごの中身をこのセッション属性に入れているから複数ページに渡ってデータを保持できるのです。次の商品を見に行くたびに買い物かごの中身がクリアされてしまっては使い物になりませんからね。
セッション属性とは開始してから破棄されるまで同一ブラウザで有効なスコープです。
セッションの破棄は、「ログアウト処理」、「ブラウザを終了する」または「セッションタイムアウト」により実行されます。
実は、前章までの知識で実現できるのは上記「①ユーザーはブラウザからIDとパスワードといった自分だけが知る情報を使ってログインする」だけです。
ですから、まずは①を実現しましょう。
1.1. IDとパスワードでログインする
以下の図5.1が処理の概要です。
ユーザーがブラウザからユーザーIDとパスワードを入力してログインボタンを押下します。
サーブレットはIdとpasswordが正しいことをチェックします。
①IDとパスワードが正しければ、messageをmember_only.jspにフォワードします。
②IDとパスワードが正しくなければ、エラー画面を表示します。

2. 不完全なログイン処理の実装
不完全ながらも、これまでの知識でログイン処理を実装してみます。
新しく「05Login」というフォルダ(ディレクトリ)を用意してその中に「login.jsp」を用意してください。

ログイン画面
以下のlogin.jspはユーザーIDとパスワードの入力を求める画面です。
ソースコードを読み込んで質問に答えてください。
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login.jsp</title>
<style>
#center {
display:flex;
justify-content: center;
align-items: center;
text-align: center;
height: 100vh;
}
</style>
</head>
<body>
<div id="center">
<form action="/03_JavaWebText/Login1" method="get">
ユーザーID:<input type="text" name="id" required><br>
パスワード:<input type="password" name="pass" required><br>
<button type="submit">ログイン</button>
</form>
</div>
</body>
</html>
- 7~15行目の記述を英字3文字で何といいましたか?
あなたの答え: |
- 21行目のフォーム部品の特徴は何ですか?
あなたの答え: |
サーブレットのソースコード
以下のLogin1.javaはIDとパスワードを認証するサーブレットです。
プログラムを読み込んで質問に答えてください。
package p05;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = { "/Login1" })
public class Login1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
String pass = request.getParameter("pass");
if ("imai".equals(id) && "p".equals(pass)) {
request.setAttribute("message", "ようこそ" + id + "さん。");
request.getRequestDispatcher("/05Login/member_only.jsp").forward(request, response);
} else {
response.sendRedirect("/03_JavaWebText/05Login/login_error.jsp");
}
}
}
- 21行目のif文でtrueの場合はどうなりますか?
あなたの答え: |
- 22行目ではどんな属性に対してどんな名前でどんなデータを格納していますか?
あなたの答え: |
次に、22行目のif文でfalseの場合、すなわち25行目のIDまたはパスワードが間違った場合を見てみましょう。
ここでは、フォワードを使っていませんね。フォワードを使ってもよいのですが、フォワードですとアドレスバーの表記が変わらないためログインしていないことが伝わりづらいため、リダイレクト処理というものを行っています。
3. フォワードとリダイレクト
画面遷移の方法にはフォワードとリダイレクトがあります。
英語の【redirect】には「re=再び」「direct=方向づける」という意味があります。データの出力先などを変更するという意味でIT業界では広く使われる言葉です。
その特徴をまとめると以下の図5.3の通りです。
下図5.3で特に注目いただきたいのは以下の4点です。

「2.ソースコード」のところでフォワードがrequestのメソッドであるのに対して、リダイレクトはresponseのメソッドであるという点
「3.遷移先のパス指定方式」のところで共通でリクエストされた現在のURLからの相対パスが指定できる点(ですので混乱を避けるためこの後のパス指定は極力相対パスを使います)
「4.典型的な処理の流れ」で、フォワードがリクエストとレスポンスを1往復交わすのに対して、リダイレクトは2往復であるという点
「5.リクエストスコープ」でリダイレクトはリクエスト属性を引き継がない点
ちなみに、リダイレクトは「5.転送可能範囲」で外部サーバーOKとなっています。したがって上記の記述を以下のようにルートパスでも、絶対パスでも、同じ結果が得られるのです。フォワードと違ってパス指定のルールがそのまま適用できると考えれば理解しやすいでしょう。(下図5.3 の「3.遷移先のパス指定方式」参照)
この研修中はリダイレクトには"/プロジェクト名"で始まるルートパスで指定することにします。相対パスは使いません。混乱を避けるためです。
response.sendRedirect("/03_JavaWebText/05Login/login_error.jsp");
なお、リダイレクト先は外部サーバーも可能です。
response.sendRedirect("https://saycon.co.jp/");
例題1
以下の画面遷移はフォワードとリダイレクト、どちらを使うべきでしょうか?
- jspをレンダリングして画面表示させる場合
- サーブレットを呼び出して画面表示を任せる場合
- 外部のサイトのページを表示する場合
- ユーザーがログインに成功した後、ユーザー専用画面を表示したい場合
実験1
フォワードで以下のようにルートパスや絶対パスで指定するのは間違っています。
一度ご自身でも確かめてみてください。
request.getRequestDispatcher("/03_JavaWebText/05Login/member_only.jsp").forward(request, response);
request.getRequestDispatcher("http://localhost:8080/03_JavaWebText/05Login/member_only.jsp").forward(request, response);
確かめた結果: |
また、リダイレクトではフォワードのように頭に/を付けたコンテキストルート以降のパスで書くことはできません。
request.getRequestDispatcher("/05Login/member_only.jsp").forward(request, response);
確かめた結果: |
ログインエラー画面のソース
以下のlogin_error.jspはログインエラー時の画面、menber_only.jspはログイン成功時の画面です。
member_only.jspの3行目の以下の記述は、リクエスト属性を指定する書き方です。後で学ぶセッション属性を指定する書き方と比べてみてください。
${requestScope.message}
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>login_error.jsp</title>
<style>
#content1{
color: red;
}
</style>
</head>
<body>
<center>
<div id="content1">
<h2>ログインエラーが発生しました。</h2>
</div>
</center>
<p style="text-align:center"><a href="login.jsp">ログイン画面へ戻る</a></p>
</body>
</html>
<%@ page pageEncoding="UTF-8" %>
メンバーだけのページです。
${requestScope.message}
ここでの問題点を指摘しておきます。
①リクエストパラメータにIDとパスワードが表示されてしまっている
②member_only.jspのURLをブラウザのアドレスバーに直接入力することでアクセスできてしまう
①のについては以下のようなアドレスバーの表示が気になっていた人もいるのではないでしょうか?
「http://localhost:8080/03_JavaWebText/Login1?id=imai&pass=p」
②の問題はひとまず置いておき、先にIDとパスワード丸見え問題を解決していきましょう。
- この問題の解決方法はなんですか?HTMLのフォームで学んだ知識でお答えください。
あなたの予想: |
4. getメソッドとpostメソッドの違い
HTMLで学んだ図5.4にあるpostメソッドの特徴をログイン処理に応用しましょう。(ちなみにシステム開発演習中は無理にpostメソッドを使う必要はありません。とりあえず全てgetメソッドにしても大丈夫です。なぜなら、postメソッドには①サーブレットが単体で実行できなくなる。②リクエストパラメータが見えなくなる。という欠点があるためです。)

例題2
以下のactionはgetとpostのどちらを使うべきでしょうか?
- 検索の条件を送信し、結果を取得する場合
- ユーザーパスワードなどの機密情報を送信するなどURLにパラメータを表示させたくない場合
- ウェブフォームを介して大量のデータ(例:ファイルアップロード)を送信する場合
<form action="/03_JavaWebText/Login2" method="post">
※差分のみ表示
@WebServlet(urlPatterns = {"/Login2"})
public class Login2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
※差分のみ表示
ブラウザのアドレスバーは以下のようになり「パスワード丸見え問題」は解決しました。
「http://localhost:8080/03_JavaWebText/Login2」
では、ここでもう少し踏み込んでgetメソッドとpostメソッドの違いについて見ていきましょう。
ブラウザには開発用のツール(ディベロッパーツール)があります。例えば、当社の新人エンジニア研修で使用しているChromeの場合はブラウザの画面を右クリックして「検証」を選びます。(ショートカットキーはF12)
当初は英語で表示されると思いますが、以下の設定画面で日本語にすることもできますので講師から説明を受けてください。

図5.6にある「ネットワーク」のタブをクリックします。

F5キーを押してリクエストとレスポンスのやり取りをもう一度実行します。
次に、「名前」のところでサーブレットのURLパターン(例.Login2)を選択して、右の「ヘッダー」をクリックします。
図5.7の上がpostメソッド、下がgetメソッドの表示例です。

- postとgetでリクエストURLはどう違いますか?
あなたの答え: |
ただし、postリクエストにするとリクエストパラメータがアドレスバーに表示されないというだけです。上図5.7の「Payload」というタブを開くとパラメータを見ることができてしまいます。httpsを使った暗号化などをしないとパケットを中継する機器からは丸見えです。くれぐれも誤解のないように。(https通信ですと「Payload」のタブ自体が無くなります)
ちなみにステータスコードが「200 OK」になっていますね。HTTPプロトコルにおいてステータスコードとは、Webサーバからのレスポンスの意味を表す3桁の数字です。
ここで当社の新人エンジニア研修で見かけるステータスコードを表5.1にまとめておきます。
ステータスコード | 意味 |
---|---|
200 | 正しく表示されている |
403 | アクセスを禁止されている |
404 | ページが見つからない |
405 | このURLではサポートされていないメソッドでアクセスした |
500 | サーバ内部エラー |
次に図5.8のように「Cookie」をクリックしてください。
名前に「JSESSIONID」、値に32文字の16進数が入っていますね。

Cookie とは、Webサイトの訪問者の情報を一時的にクライアントに保存するための仕組みです。Cookie の目的はユーザーの識別です。近年 Cookie を使った広告のトラッキングが問題になっていることをご存じの方もいるかと思います。
そして今回作りたいログイン処理もこの Cookie を使った仕組みなのです。
次に、 JSESSIONID とはJ2EEを使用したWebアプリケーションにおいてデフォルトで使用されるセッションIDを表す番号です。JSESSIONID の先頭のJはJavaのJなのですね。
セッション【session】とは、ブラウザとWebサーバの一連の複数のリクエストとレスポンスの活動期間のことです。(例えば、複数の質問に回答する時間をQ&Aセッションといいますね。英語のsessionには複数の送信と受信の一連の流れ、というような意味があるのです)このセッションごとにIDが付いているわけです。
実は一般的なログイン処理はこのセッションの仕組みを利用しているのです。(注:他にも方法はあります)
次はこのセッションの仕組みを使ってログイン処理を実装しましょう。
5. セッションIDの仕組み
セッションIDの仕組みを解説します。
- クライアント(ブラウザ)からサーバにリクエストが送られます
- サーバはセッションIDを生成します
- サーバはレスポンスにセッションIDを入れてクライアントに返します
- クライアントはセッションIDをCookieに保存します
- 以降、クライアントは全てのリクエストにセッションIDを入れて送ります
- サーバはクライアントから送られたセッションIDとサーバに保存されたセッションIDを照合することによりユーザーを認証します
- それ以降は上記5,6の手順でリクエストとレスポンスを繰り返します
- セッションIDのタイムアウト(デフォルトでは30分間)または破棄(大抵はログアウト)するまでセッションは有効です
パスワードとは異なりセッションIDは1回限りの意味のない16進数なので盗まれたとしても実害は少ないです。
(ただし、そのセッションIDを悪用する攻撃もありますので注意が必要です。もちろん現在皆さんがお使いのブラウザでは簡単には盗まれないようになっていますのでひとまずは安心して大丈夫ですが)

調べてみましょう
Cookieの保存場所を見てみましょう。
当社の新人研修で使用しているGoogle Chromeの場合のCookieは、C:\Users\Your_User_Name\AppData\Local\Google\Chrome\User Data\Default\Network
にある単一のファイルに保存されています(Your_User_Nameを実際のユーザーアカウント名に置き換えてください)。
なお、このファイルはユーザーが読むことや編集することはできませんので試してみましょう。
調べたことのメモ: |
5.1. セッションを使ったログイン処理を実装する
セッションを使って次のログイン処理(再掲)を実現することにしましょう。以下の②~⑥に対応した処理を作っていきます。
①ユーザーはブラウザからIDとパスワードといった自分だけが知る情報を使ってログインする(対応済み)
②ログイン後はそのユーザーだけが見られるページに遷移できるようになる
③ログイン中は同じブラウザで他のタブを開いてもログインされたままである
④しかし、同じユーザーが別のブラウザで同じページにアクセスしても再度ログイン処理が必要である
⑤ログアウト処理をする、ブラウザを終了するまたは一定時間(大抵は30分間だが銀行のように5分程度と短い場合も)が経過するとログアウトする
⑥ログアウトしてからブラウザの戻るボタンを押すと元のログイン状態に戻らないセキュリティを強化したサイトが存在する
セッションIDに紐づく形でセッション属性という記憶領域が用意されています。
セッション属性の概要は下図5.10のとおりです。
リクエスト属性に似ていますが、リクエスト属性は1つのリクエストだけがスコープでした。しかし、セッション属性は複数のリクエストにまたがって有効なスコープです。セッション属性は同一ブラウザであれば全てのページで有効なスコープであるともいえます。したがってセッションを使ったWebアプリケーションをテストする際には注意が必要です。例えばWebブラウザのタブを全て閉じてからテストしないと、セッション属性にデータが残っていて意図しない動作をすることがあります。

<login2.jsp>はコピーして <login3.jsp> として使用します。
飛び先だけ次の<Login3.java>に変更しておいてください。
package p05;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet(urlPatterns = { "/Login3" })
public class Login3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
String pass = request.getParameter("pass");
HttpSession session = request.getSession();
session.setAttribute("id", id);
session.setAttribute("message", "こんにちは" + id + "さん。");
if ("imai".equals(id) && "p".equals(pass)) {
request.getRequestDispatcher("/05Login/member_only2.jsp").forward(request, response);
System.out.println(id);
} else {
response.sendRedirect("/03_JavaWebText/05Login/login_error2.jsp");
}
}
}
- <Login2.java> からの変更点はなんですか?
あなたの答え: |
HttpSession session = request.getSession();
このように記述することでセッションを取得します。この記述はセッション属性を扱うすべてのServletで必要となります。
リクエスト属性はdoPostやdoGetメソッドの引数だったため宣言が不要でしたね。対して、セッション属性はHttpSessionクラスの宣言が必要なのですね。
session.setAttribute("id", id);
session.setAttribute("message", "こんにちは" + id + "さん。");
このように記述することでセッション属性にオブジェクトを名前をつけて保存することができます。メソッド名(setAttribute)
は全くリクエスト属性のときと同じと覚えましょう。
- セッション属性から属性を取得するメソッドの書き方を予測してみてください。
あなたの答え: |
ログインしないと見られないページは次のmember_only2.jspに記述されています。
menber_only2.jspの17行目の以下の記述
${sessionScope.message}
は、セッション属性を指定する書き方です。以前のリクエスト属性を指定する書き方と比べてみてください。(15行目はメニューの読み込み処理で、次の章で解説します)
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>member_only2.jsp</title>
<c:if test="${id == null}" >
<c:redirect url="login_include_menu.jsp" />
</c:if>
</head>
<body>
<p><%@ include file="menu.jsp" %></p>
<br>メンバーだけのページです。
${sessionScope.message}<br>
<a href="05Login/video.jsp" target="_blank">別のタブでビデオを見る</a><br>
</body>
</html>
- 2行目の記述は何のためでしたか?
あなたの答え: |
- 8~10行目の記述は何のためにあるか推測してみてください。
あなたの答え: |
- この <member_only2.jsp>を単体で実行したらどうなりますか?
あなたの答え: |
今回、“jstl/core”という記述があります。JSTLのコアタグというものを使用するための記述です。詳細は次回にしたいと思いますが、ここでも簡単に解説すると、
<c:if>
から</c:if>
までが一つのif文になっています。
そして、「test=true」であれば、ifブロックの内容を実行し、「test=false」であれば何もしない、という処理になっています。
<c:redirect url="login3.jsp"/>
というタグは文字通り指定のURLにリダイレクトするという意味です。(なお、このようにjspからjspに遷移することはMVCモデルの原則から外れるため推奨されません)
以下のvideo.jspはログイン後にメンバー専用でビデオが見られるページです。
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>video.jsp</title>
</head>
<body>
<p><%@ include file="menu.jsp" %></p>
${sessionScope.message}ビデオを楽しんでください。<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/LA95vAwTn-M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</body>
</html>
ちなみに、私達はJavaSEで学んだように{ }(波括弧)を一つのブロックとして考えることが半ばあたりまえになっています。しかし、<c:if>
から</c:if>
のようにif文の始まりと終わりを明示するプログラム言語も多く存在します。いまのうちに慣れておきましょう。
5.2 セッション属性とリクエスト属性の使い分け
セッション属性は有効範囲が広いため、新人エンジニアの中にはリクエスト属性ではなくセッション属性に何でも入れようとする人がいます。しかし、それは良くないことです。なぜなら、アプリケーションサーバのメモリを圧迫してしまうからです。
リクエスト属性は一つのリクエスト間だけ有効
セッション属性は複数のリクエスト間でも有効
ということは、「リクエスト属性はすぐにサーバーのメモリから消えるが、セッション属性は残ってしまう」のです。この性質を理解して適切に使い分けましょう。「使い捨て」の方が都合の良いことも多いものです。特にITの世界では「使い捨て」といってもデータですから環境問題は生じないので積極的に使い捨てましょう。
下図5.11はセッション属性とリクエスト属性の比較です。

例題3
以下の情報はリクエスト属性、セッション属性どちらに保存すべきでしょうか?
- ユーザーがログインしている間は常に必要となる登録ユーザーの個人情報
- ユーザーが買い物かごに入れた商品情報
- データベースから取得した画面表示のための商品情報
例題4
<video.jsp> にもログイン後でなければアクセスできないような記述を加えなさい。
6. メニューをインクルードする
ここで、下図5.12のようにWebアプリケーションらしくログイン後の各ページにはメニューメニューがある状態にしたいと思います。

メニューとして以下のmenu.jspをご用意ください。
<%@ page pageEncoding="UTF-8" %>
<a href="login_include_menu.jsp">ログイン</a>
<a href="/03_JavaWebText/Logout">ログアウト</a>
<a href="#">商品検索</a>
<a href="#">買い物かご</a>
<%
response.setHeader("Cache-Control", "no-cache,no-store, must-revalidate");//HTTP1.1をサポートしているブラウザ向けの記述
response.setHeader("Pragma", "no-cache");//HTTP1.0をサポートしているブラウザ向けの記述
response.setHeader("Expires", "0");//プロキシサーバー対策として、過去の日時を入力して強制的にキャッシュを無効化する
%>
商品検索や買い物かごのリンク先は今はダミー(#)です。また、7行目~11行目のスクリプトレットの記述はすべてブラウザバック対策のための記述です。コメントにその詳細を記述しておきました。
ブラウザバックとは、Webブラウザの「戻る」操作で直前に開いていたページに遷移することです。ログアウトしたにも関わらず、ブラウザバックでログイン中の画面に戻れる、とすると例えば、ネットカフェなどの共用のパソコンではセキュリティの問題があることは言うまでもありません。
ログインのリンク先のJSPはこれから以下のlogin_include_menu.jspを作ります。
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<title>login_include_menu.jsp</title>
<style>
#center {
height: 200px;
width: 300px;
position: absolute;
left: 50%;
top: 50%;
margin-top: -100px;
margin-left: -150px;
text-align: center;
}
</style>
</head>
<body>
<p><%@ include file="menu.jsp" %></p>
<div id="center">
<form action="/03_JavaWebText/Login3" method="post">
ユーザーID:<input type="text" name="id" required><br>
パスワード:<input type="password" name="pass" required><br>
<button type="submit">ログイン</button>
</form>
</div>
</body>
</html>
- 18行目では何をしていると推測されますか?
あなたの答え: |
7. ログアウト処理の実装
次にログアウト処理を考えてみましょう。
私達はこれまでユーザーがログイン済みかどうかをセッション属性にあるidという名前のオブジェクトがnullで“ない”ということによって確かめてきました。したがって、ログアウト処理はこのidというオブジェクトを削除してnullにすることによって実現できそうです。
以下のLogout.javaはセッションにあるidという名前の属性を削除して、ログイン画面にリダイレクト処理をするサーブレットです。このプログラムを読んで質問に答えてください。
package p05;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet(urlPatterns = {"/Logout"})
public class Logout extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
session.removeAttribute("id");
response.sendRedirect("/05Login/login_post3.jsp");
}
}
- HttpSession session = request.getSession(); という記述は、なぜ必要なのでしたか?
あなたの答え: |
- session.removeAttribute("id");という記述では何をしていると推測されますか?
あなたの答え: |
セッション属性を扱うすべてのServletでセッションの宣言が必要になることを銘記してください。
実験
例題6
ログイン後のページ全てにmenu.jspを組み込みなさい。
また、ログアウト後のブラウザバック対策ができていることを確認しなさい。
※なお、開発中はブラウザバック対策を外した方が楽かもしれません。
例題7
各社でプロジェクト名を決めて0からログインの仕組みを作りなさい。可能な限りこのテキストでやったことを再現すること。(できるだけテキストを見ないように)
例題8
これまで作成してきた数当てゲームを改良して複数回のチャレンジが可能なようにしなさい。
また、「もう一度プレイする」のリンクをクリックすることで再度プレイできるようにしなさい。
各チームで新プロジェクトの名前を決めて作成すること。

使用ファイル:index.html,result.jsp,result2.jsp,GameServlet.java,Kazuate.java
なお、エラー処理は後回しにしてよい。
また、複数のブラウザから同時に実行して以下のようにそれぞれ違った答えになることを確認すること。

例題9
上記例題5からこの章で登場した<c:if>タグを使い、不要なHTML要素を削除しなさい。

今回はログイン処理の実装方法を通じてセッションについて学びました。
Webページというものは本来1ページ、1ページが独立していて、ページをまたいでデータを引き継ぐ仕組みがありません。このようにhttp通信のリクエストとレスポンスがそれぞれ独立していて他の http通信にデータを引き継がないことをステートレス【stateless】といいます。【state】= 状態 が【less】=(引き継げ)ないというわけでしたね。
本来http通信はステートレスであり、一対のリクエストとレスポンスで通信は終了します。しかし、複数のリクエストとレスポンスを同じものとして扱うことができなければ、ログイン処理や買い物かごの処理は実現できません。ページをまたぐごとにユーザーを忘れてしまったり、買物かごの中身が消えてしまったら使い物になりませんね。
そこで必要となるのがセッションです。
Webアプリケーションは、本来ステートレスとして作られたhttp通信を使って擬似的にステートフルにしてオンライン商取引などに使っているわけです。そのため、かなり無理をしている(?)感じは否めないかと思います。
ブラウザの表示がおかしいときは?
Webシステムを開発しているとキャッシュが邪魔をして想定外の動きになることがあります。そんな時は以下の対策を試してみてください。
- ブラウザのスーパーリロード(Ctrl + F5)を試す
- ブラウザを再起動する(すべてのタブを閉じる)
- サーバーのタブからTomcatを「停止」して「クリーン」してから再度実行する
- 別のブラウザで実行する(例えば普段Edgeを使って開発している場合はChromeで実行する)
- ブラウザのゲストモードで実行する(設定方法は以下のとおりですが、詳しくは講師がお話しします)

Eclipseのクリーン起動
Eclipseのクリーン起動(Clean Start)は、Eclipse統合開発環境(IDE)を特定の状態で起動するための方法です。通常、Eclipseは前回のセッションの状態を記憶しており、起動時に前回の状態を復元します。しかし、クリーン起動を行うと、前回の状態やキャッシュを無視して、新しい状態でEclipseを起動することができます。
クリーン起動は通常eclipse.exeと同じフォルダに入っています。「eclipse.exe -clean.cmd」アイコンをダブルクリックします。

「ポート番号を変更する必要があります」となったときは?
これは、何らかの原因でtomcatが終了していない間に新しくtomcatを起動したことが原因です。

tomcatが入っているフォルダの中に「kill-8080-port.cmd」というツールがありませんか?

これをダブルクリックすることでサーバーをkillすることができ、問題解決につながります。
「「Tomcatxxに問題が発生しました。Tomcatxxは始動に失敗しました。」」となったときは?
サーバーを削除して作り直すことも有効です。
具体的な方法は講師にお尋ねください。
<まとめ:隣の人に正しく説明できたらチェックを付けましょう>
□ ログイン処理を実現するにはセッションという仕組みを理解することが必要
□ セッション属性は同一ブラウザで開始してから破棄されるまで、同一ユーザー(ブラウザ)であれば全てのページで有効なスコープである
□ 画面遷移の方法にはフォワードとリダイレクトがある
□ フォワードはリクエスト属性を引き継ぐがリダイレクトは引き継がない(ただし、リクエストパラメータを付加することは可能)
□研修中はリダイレクトには"/プロジェクト名"で始まるルートパスで指定する(フォワードにはプロジェクト名の後ろの“/”で始まるコンテキストパスを指定する)
□ クライアントはセッションIDをCookieに保存する
□ サーバはクライアントから送られたセッションIDとサーバに保存されたセッションIDを照合することによりユーザーを認証する
□ HttpSession session = request.getSession() と記述することでセッションを取得する。この記述はセッション属性を扱うすべてのServletで必要となる
□ セッション属性へのオブジェクトの出し入れのメソッド名はリクエスト属性のときと同じgetAttribute/setAttributeである
□ http通信はステートレスなためページをまたいでデータを保持するにはセッションが必要である
次回は、JavaBeansを学んでいきます。
JavaBeansを使うことで今回のセッション属性にオブジェクトをまるごと入れて複数ページをまたいだ処理が可能になります。例えば、買物かごのような仕組みも実現できるようになります。
IT企業向け新人研修おすすめ資料 無料公開中 (saycon.co.jp)