LoginSignup
2
2

More than 1 year has passed since last update.

サーブレットでセッション管理を行う

Posted at

はじめに

こんばんわ、きりです。
本記事はNablarchを使ってみようのサブ記事として作成しております。

今回はセッション管理について整理します。
本記事ではセッション管理を利用して、(超)簡易的なログインの仕組みを実装してみようと思います。

本記事以外のコンテンツはこちらから閲覧可能です。

なるべく、初心者目線で作成するつもりですが、分かりづらい部分ありましたら、コメント頂きたいです。

セションとは

セッションとは、クライアントがブラウザなどのアプリケーションでWebサーバーとの接続を開始し、複数回のリクエストとレスポンスのやり取りを行った後、接続を終了するまでの一連の流れを指します。

セッション管理
典型的な HTTP セッション
HTTPセッション

セッション管理とは

セッション管理とは、1つのセッションにおける、クライアントとサーバー間でその情報を保持し、アクセス制御を一つの集合体として管理する仕組みを指します。

セッション管理を行うことで、セッションの中で行われた操作情報や会員サイトなどにおけるログイン情報などを保持することが可能となり、通信負荷の軽減や処理の高速化を行える可能性があります。

セッション管理

# セッションの作成と存在確認
セッションの作成と存在確認には getSessionメソッド を利用します。

引数にはtrueまたはfalseが指定可能で、falseの場合はセッション存在の有無を確認し、セッション情報またはnullを返却します。
trueを指定した場合は、セッションがまだ作成されていなければ新たにセッションを作成し、セッション情報を返却します。既に存在する場合は既存のセッション情報を返却します。
なお、セッションにはセッションIDと呼ばれるセッション毎の一意な値が割り振られます。

getSessionメソッドはHttpServletRequestクラスのメソッドのため、サーブレットの引数として渡されたrequestオブジェクトより呼び出しが可能です。

セッションの破棄

getSessionメソッドより取得したHttpSession側のオブジェクトからinvalidate関数を呼び出すことでセッションが破棄されます。

invalidate

セッションへのオブジェクト追加と参照

セッションに情報を登録することで、同じセッションであれば別のリクエストが呼び出された場合も値が参照可能です。
セッションへのオブジェクト追加はHttpSessionクラスのsetAttibutes,値を参照するときはgetAttributesを使用します。
HttpSessionのオブジェクトはサーブレットの引数のrequestよりgetSessionすることで取得できます。

setAttributes
getAttributes

セッション管理を利用した簡易ログインシステム

概要

  • ログイン画面を作成し、名前の入力欄とログインボタンだけ配置します
  • ログイン画面でログインボタンを押下すると、セッションを再作成し名前をセッションへ名前属性として記録し、ホーム画面へ遷移します
  • ホーム画面ではセッションから名前属性を取得し画面へ表示します
  • ホーム画面でログアウトボタンを押下すると、セッションを破棄し、ログイン画面へ遷移します
  • web.xmlを編集し、ルートアクセス時にHomeサーブレットへ遷移するように設定します

ファイルの作成

  • サーブレット
パッケージ名 クラス名 作成されるパス
com.example Home src/main/java/com/example/Home.java
com.example.session Login src/main/java/com/example/session/Login.java
com.example.session Logout src/main/java/com/example/session/Logout.java

※サーブレットの作成方法はこちらを御覧ください

  • JSP
ファイル名 作成されるパス
Home.jsp src/main/webapp/View/Home/Home.jsp
Login.jsp src/main/webapp/View/Session/Session.jsp

※JSPの作成方法はこちらを御覧ください

各ファイルの実装

Home.jsp

Home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
  // Servletのデータ受け取り
  request.setCharacterEncoding("UTF8");
  String strName = (String) request.getAttribute("name");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ホーム画面</title>
</head>
<body>
  <%=strName %>さん、こんにちわ
  <br>
  <br>
  <form action="<%= request.getContextPath() %>/Logout" method="post">
    <input type="submit" value="ログアウトする">
  </form>
</body>
</body>
</html>
  • リクエストからname属性を抽出し画面に表示します
  • ログアウトボタンを作成し、Logoutサーブレットを呼び出します

Login.jsp

Login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ログイン画面</title>
</head>
<body>
  <form action="<%= request.getContextPath() %>/Login" method="post">
    <h2>ログイン名</h2>
    <input type="text" name="name" />
    <input type="submit" value="ログイン">
  </form>
</body>
</html>
  • 入力欄を作成し、ログインボタン押下時にLoginサーブレットへ遷移します

Login.java

Login.java
package com.example.session;

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;

/**
 * Servlet implementation class Login
 */
@WebServlet("/Login")
public class Login extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Login() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.getRequestDispatcher("View/Session/Login.jsp").forward(request, response);
  }

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // ログイン名をリクエストから取得する
    HttpSession session = request.getSession(false);
    // 既にセッションが存在する場合は一度破棄する
    if (session != null) {
      log("セッション破棄 セッションID=[" + session.getId() + "]");
      session.invalidate();
    }

    try {
      // セッションを新規で作成する
      session = request.getSession(true);
      log("セッション作成 セッションID=[" + session.getId() + "]");

      request.setCharacterEncoding("UTF-8");
      // 各フォームデータを取得する
      String name = request.getParameter("name");

      // ログイン名をセッションで保持する
      session.setAttribute("name", name);

      // ログイン後ホーム画面へ自動遷移する
      request.getRequestDispatcher("Home").forward(request, response);
    } catch (Exception e) {
      log("セッション作成 失敗");
      // 例外によりセッションの作成に失敗
      e.printStackTrace();
    }
  }

}
  • GET時はLogin.jspを表示します
  • Login.jspからポストされた場合はセッションを破棄 -> セッションの作成し、リクエストから取得した名前情報をセッションを保持します
  • 処理完了後、Homeサーブレットへフォーワードします

Home.java

Home.java
package com.example;

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;

/**
 * Servlet implementation class Home
 */
@WebServlet("/Home")
public class Home extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Home() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setCharacterEncoding("UTF8");

    String name = null;
    HttpSession session = request.getSession(false);
    // name属性が存在しない場合はセッション情報なしとして取り扱う
    if (session != null && (name = (String) session.getAttribute("name")) == null) {
      session = null;
    }

    // セッション情報がないもしくは期待した状態でなければログイン画面に遷移する
    if (session == null) {
      request.getRequestDispatcher("Login").forward(request, response);
      return;
    }

    // ホーム画面に名前を表示する
    request.setAttribute("name", name);

    // ホーム画面を表示する
    request.getRequestDispatcher("View/Home/Home.jsp").forward(request, response);
  }

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
  }

}
  • セッションの有無を確認し存在しない場合はLoginサーブレットへフォワードします
  • セッションが存在する場合も名前属性が存在しない場合は、ログインを経由していないためLoginサーブレットへフォワードします
  • セッションが存在し名前属性が取得できた場合は、リクエストに設定しHomeサーブレットへフォワードします

Logout.java

Logout.java
package com.example.session;

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;

/**
 * Servlet implementation class Logout
 */
@WebServlet("/Logout")
public class Logout extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Logout() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // ログアウト時はセッションを破棄する
    HttpSession session = request.getSession(false);
    // 既にセッションが存在する場合は一度破棄する
    if (session != null) {
      log("セッション破棄 セッションID=[" + session.getId() + "]");
      session.invalidate();
    }

    // セッション破棄後にログイン画面に遷移する
    request.getRequestDispatcher("View/Session/Login.jsp").forward(request, response);
  }
}
  • セッションを破棄し、ログイン画面へフォワードします

ルート画面の設定

web.xml
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>Home</servlet-name>
    <servlet-class>com.example.Home</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Home</servlet-name>
    <url-pattern></url-pattern>
  </servlet-mapping>
</web-app>

これまでweb.xmlについては触れてきませんでしたが、サーブレットの設定は主にweb.xmlで管理しています。
今回はservlet-mappingタグにて、ルートアクセス時()にHomeサーブレットへ遷移するように設定しました。
Homeサーブレットの設定はservletタグにて行っています。

LoginサーブレットやLogoutサーブレットは各ファイルにて@WebServletを指定しているので、web.xmlの設定なくともサーブレットとして認識されているようです。

動作確認

ルートにアクセス

image.png

未ログインのため、ログイン画面に遷移します

ブラウザの開発ツールからレスポンスヘッダーを確認すると、JSESSIONIDというのがサーブレット側で作成されたセッションIDです。
自動でセッションが生成されたようです。
image.png

ホーム画面

image.png

名前を入力後、ログインボタンを押下します

image.png

ログイン時に指定した名前が画面に表示されます

リクエスト時とレスポンスのJSESSIONIDが異なることからセッションIDが新たに作成されたことがわかります。
image.png

ログアウト

image.png

ログアウト後、ログイン画面に遷移します。

最後に

今回はセッション管理について整理しました。
セッションを利用することで、サーバ側でクライアント情報を保持することができるため、実装の幅が広がるかと思います。
参考になれば嬉しいです。

他の記事についてはこちらから御覧ください。

参考リンク

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2