SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

WTPではじめるサーバサイドJava入門

サーバサイドJava入門 ログイン処理とサイト攻撃対策の基礎

第4回 セッションとクッキー


ログイン処理の流れ

 ここでは、index_action.jspでログインの認証処理をしています。まず、送られた情報を取り出し、nullだった場合は空のStringを入れておきます。これは、その後の処理でnullチェックをしないで済むようにという配慮です。

String id = request.getParameter("id");
id = id == null ? "" : id;
String pass = request.getParameter("pass");
pass = pass == null ? "" : pass;

 そして、送信されたIDとパスワードがそれぞれ正しいものかどうかをチェックしています。ここではサンプルということで、単に変数に用意してあるものとequalsで比較をしているだけですが、より本格的なシステムともなればデータベースなどに問い合わせてIDとパスワードが登録されているか調べるなどの処理を行うことになるでしょう。

if (id.equals(id_str) && pass.equals(pass_str)){

 そして、送信された情報が正しければ、セッションの最長接続時間を設定し、"login"という名前のアトリビュートをsessionに保存し、page.jspにリダイレクトします。

session.setMaxInactiveInterval(60 * 10);
session.setAttribute("login","true");
pageContext.forward("./page.jsp");

 情報が誤りならば、"login"に"false"を保管し、ログインページに戻ります。

session.setAttribute("login","false");
pageContext.forward("./index.jsp");

 このように、ログインがされていれば、セッションに"login"という名前のアトリビュートが作成され、そこにログイン済みである"true"が保管されます。ログインに失敗した場合には"false"が保管されます。従って、この値をチェックすればログイン済みかどうか分かるわけです。page.jspの処理を見てみましょう。

String login = (String)session.getAttribute("login");
if (login == null || !login.equals("true")){
    pageContext.forward("./index.jsp");
}

 このように、"login"の値を取り出し、それがnullであったり、"true"でない場合にはindex.jspにリダイレクトをしています。

 ここで作成したのは、ごくごく基本的なログインシステムですが、基本的な考え方は分かったことと思います。セッションのように、サーバにアクセスしてからタイムアウトされるまでの間、常に値などを保持し続けることのできるものが用意される利点というのが少しは感じられたのではないでしょうか。

クッキーの利用

 このセッションという機能の実現には、あるものが大きく関与しています。それは「クッキー」です。ためしに、WebブラウザのクッキーをOFFにして、先ほどのログインシステムにアクセスしてみてください。そしてログイン後、page.jspに直接アクセスしてみましょう。おそらく、ログインページに戻されるはずです。ログインしているはずなのに、認識されないのです。

 その理由は、クッキーがOFFになったために、セッションがうまく機能しなかったからです。ログインシステムにアクセスした後、Webブラウザのクッキー情報をチェックしてみましょう。localhostのクッキーとして、こんなものが保存されているのが分かるはずです。

名前:JSESSIONID
内容:35CC39E66842809263A2139E541BF6CA
Firefoxでlocalhostのクッキー情報を表示したところ。JSESSIONIDというクッキーが保存されているのが分かる。
Firefoxでlocalhostのクッキー情報を表示したところ。JSESSIONIDというクッキーが保存されているのが分かる。

 内容の値はそれぞれ違っていると思いますが、このようにJSESSIONIDという名前のクッキーが保管されているはずです。実をいえば、これがセッションの正体だったのです。サーバでは、このJSESSIONIDの値をチェックし、それが前回アクセスしたのと同じクライアントかどうかを確認していたのです。

 まぁ、セッションにはこの他にクエリー文字を使って識別IDを送るような方式もあり、必ずしも「常にクッキーでセッション情報を保管する」というわけではないのですが、このようにクッキーは「クライアント側に情報を保管できる機能」として私たちが気づかないところでいろいろと使われています。

 JSPからクッキーを使うことももちろん可能です。クッキーは、Cookieクラスとして用意されています。クッキーを新たに作成する場合には、このインスタンスを作成し、response.addCookieというメソッドを使って追加します。

 保存されているクッキーを利用する場合には、request.getCookiesというメソッドを使ってクッキーを取得します。ただし、これで得られるのはCookieインスタンスではなく、Cookieの配列です。つまり、保管されている全クッキーが配列として返されるのです。Cookieには、getNamegetValueといったクッキーの名前や値を取り出すためのメソッドが用意されていますので、これを使って1つ1つのCookieの名前をチェックし、必要なクッキーを取り出します。

ログインIDをクッキーに保管する

 ではクッキーの利用例として、先ほどのログインシステムに「ログインページを開いたら、前回のログインIDが自動表示される」という機能をつけてみましょう。要するに、送信されたログインIDをクッキーに保管し、index.jspにアクセスしたときにそのクッキーを読み込んでIDフィールドのvalueに設定するわけです。

index.jspのリスト
<%@ page language="java" contentType="text/html; charset=windows-31j"
    pageEncoding="windows-31j"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
request.setCharacterEncoding("windows-31j");
String msg = "IDとパスワードを入力ください。";
if (session.getAttribute("login") != null &&
    !session.getAttribute("login").equals("true"))
    msg = "※ログインに失敗しました。";
Cookie[] cookies = request.getCookies();
String pre_id = "";
for(Cookie cookie:cookies)
    pre_id = cookie.getName().equals("id") ? cookie.getValue():pre_id;
%>
<html>
    <head>
        <meta http-equiv="Content-Type"
content="text/html; charset=windows-31j">
<title>JSP SAMPLE</title> </head> <body> <%=msg %><br> <form method="post" action="./index_action.jsp"> <table> <tr> <td>ID:</td><td><input type="text"
name="id" value="<%=pre_id %>">
</td> </tr><tr> <td>PASS:</td><td><input type="password" name="pass"></td> </tr><tr> <td></td><td><input type="submit"></td> </tr> </table> </form> </body> </html>
index_action.jspのリスト
<%@ page language="java" contentType="text/html; charset=windows-31j"
    pageEncoding="windows-31j"%>

<%
String id_str = "code";
String pass_str = "zine";

request.setCharacterEncoding("windows-31j");
String id = request.getParameter("id");
id = id == null ? "" : id;
String pass = request.getParameter("pass");
pass = pass == null ? "" : pass;

Cookie cookie = new Cookie("id",id);
cookie.setMaxAge(60 * 60 * 24 * 3);
response.addCookie(cookie);
if (id.equals(id_str) && pass.equals(pass_str)){
    session.setMaxInactiveInterval(60 * 10);
    session.setAttribute("login","true");
    pageContext.forward("./page.jsp");
} else {
    session.setAttribute("login","false");
    pageContext.forward("./index.jsp");
}
%>
一度ログインすると、次にアクセスしたときには前回のIDが自動的に入力される。
一度ログインすると、次にアクセスしたときには前回のIDが自動的に入力される。

 送信されたフォームの情報から、IDをクッキーに保管するのは、index_action.jspで行っています。以下の部分です。

Cookie cookie = new Cookie("id",id);
cookie.setMaxAge(60 * 60 * 24 * 3);
response.addCookie(cookie);

 new Cookieでクッキーを作成し、それをaddCookieしています。その前に「setMaxAge」とありますが、これはクッキーの保存期間を指定するものです。これは秒単位で計算した値を引数にして指定します。ここでは、60 * 60 * 24 * 3 = 3日後まで保管するようにしています。このsetMaxAgeを設定しないと、セッションが切れた段階でクッキーは消去されるので注意が必要です。

 そしてindex.jspでは、最初に全クッキーを調べ、"id"というクッキーがあれば、その値を入力フィールドに表示する処理を追加しておきます。

Cookie[] cookies = request.getCookies();
String pre_id = "";
for(Cookie cookie:cookies)
    pre_id = cookie.getName().equals("id") ? cookie.getValue():pre_id;

 これがその処理部分です。getCookiesでCookie配列を取得した後、forの繰り返しを使い、すべてのCookieに対してgetNameした値が"id"かどうかをチェックしています。クッキーは、このように取り出す際に「どれが必要な値か」をいちいち調べないといけないという点が少々面倒ですが、クライアント側に必要な情報を保管できるものとしていろいろ使い道があります。

Firefoxで再びlocalhostのクッキーを見てみると、「id」というクッキーに「code」という値が保管されているのが確認できた。
Firefoxで再びlocalhostのクッキーを見てみると、「id」というクッキーに「code」という値が保管されているのが確認できた。

 ただし、あまり大きなデータを保管することはできないので注意してください。クッキーは、ブラウザにより実装が異なります。RFC2109、RFC2965などを参考に考えると、1つの値について最大4096バイト、変数の数は最大20個以内というのが一つの基準となりそうです。これを超えると、値の保証は難しいでしょう。

次のページ
サイト攻撃とセキュリティについて

この記事は参考になりましたか?

WTPではじめるサーバサイドJava入門連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1418 2008/08/19 20:22

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー