TomcatサーバSessionの実装


「HTTP権威ガイド」と「How Tomcat Works」の話を結びつけて、私が理解しているSessionとTomcatの下での実現方法!
セシオンって何?
正式な討論を始める前に、私たちはまずいくつかの原理的な問題を検討して、何がsessionで、それは何をすることができます!私达は毎日すべて各种のウェブサイトをブラウズして、异なるユーザーはウェブサイトの目的をブラウズして异なって、このウェブサイトの上で残した歴史も异なって、个性的なサービスを提供するために、サーバーはユーザーを记录して识别する必要があります!1人のユーザーが異なる場所で、異なるデバイスを利用してウェブサイトにアクセスすることができ、サーバはどのように「私は誰ですか」を知っていますか?多くの人がすぐにユーザー名とパスワードを考えています.そう、そうです.これは確かに方法です.しかし、ウェブサイトへのアクセスは連続的なプロセスであり、アクセスするたびにユーザー名とパスワードを携帯することはユーザーのリスクを高め、さらに重要なのは、非登録ユーザーの問題をどのように解決するか、一部のユーザーは毎日ニュースサイトを開くことに慣れているが、彼は情報を閲覧するだけで、個人情報を入力してウェブサイトに登録したくない.このようなユーザーはどのように個性的なサービスを提供しているのだろうか.
現実の生活の中で政府がどのように「私が誰なのか」を認識し、差別的なサービスを提供しているかを見てみましょう.私たちはみな身分証明書を持っていて、政府機関が送ってくれたのです.身分証明書は、名前、身分証明書番号、住所など、一人の基本的な情報にすぎません.あなたの学歴、あなたの結婚状況は記録されません.私がこれらの情報を必要とするとき、私たちは身分証明書を提供して、関連する部門は関連証明書を提供して、例えば多くの省が不動産を購入する時、未婚の人は独身証明書を提供する必要があります.私たちは相応の政府機関に身分証明書を提供すれば、これらの「認められた」情報を得ることができます.抽象的に理解すると、政府は個人に身分証明書を発行し、政府サービスが必要な場合は、身分証明書を提供するだけで、政府は自分で維持しているデータから、より多くの個人情報を取得し、差別化サービスを提供することができます.身分証明書には有効期間があり、身分証明書が期限切れになった場合、新しい申請が必要です.そうしないと、持っている身分証明書は無効になります.
では、このプロセスに倣って、ウェブサイトのサーバーはユーザーに身分証明書を「発行」して、ユーザーはアクセスするたびにこの身分証明書を持っていて、ウェブサイトのサーバーはこの身分証明書に基づいてユーザーのもっと多くの情報を取得して、このように個性的なサービスを取得することができますか?身分証明書が期限切れになった場合、ユーザーが新しい申請をする必要があります.
今、私たちが議論しなければならない問題がだんだん浮上してきた.私たちとサーバの間のインタラクションは、Sessionと理解することができます.率直な翻訳はセッションですが、私たちが持っているアイデンティティ情報は、Cookieによって実現されます.
「HTTP権威ガイド」では、Cookieによるアイデンティティ認証プロセスがこのように記述されている.
Cookieの役割はサーバーのようなもので、ユーザーに送った身分証明書には、「私はXXと申します.住所」と書かれています.ユーザーがサーバーにアクセスするとき、これらの情報を持っていて、サーバーはこれらの情報をすべて読み取ります.
ユーザーがWebサイトに初めてアクセスしたとき、サーバはユーザーについて何も知らなかった.ユーザーが次にアクセスするときに、このユーザーを認識できるように、サイトはユーザーに独自のクッキーを「撮る」ことで、サーバがこのユーザーを認識することができます.Cookieは、名前=値という情報からなるリストを含み、Set−CookieまたはSet−Cookie 2 HTTP応答ヘッダを介してユーザに返信する.ブラウザが次回サイトにアクセスする際には,Cookieリクエストヘッダにサーバから送られてきたCookieデータをそのまま携帯する.
実はCookieは任意の情報を携帯することができて、それはサーバーがユーザーSessionの最もよく使う手段の1種を維持するのです.サーバーは本当にユーザーにアクセスして、唯一のIDを持つSessionを作成し、Set-Cookieを通じてこのSessionIdをユーザーに貼り付けます.ユーザがサーバにアクセスするたびにこのSessionIdを持っていると,サーバはSessionIdによって対応するSessionオブジェクトを探し出し,ユーザを識別することができる.
もちろんこれは依然として抽象的な記述であり,異なるWebサーバがこのメカニズムを実現するのにも大きな違いがある.次に、Tomcatのソースコードから、WebサーバとしてTomcatがどのようにSessionを維持し、Cookieに基づいてユーザーSessionを取得するかを見てみましょう.
Tomcat Sessionの実装
大まかな流れは次のような手順に分けることができます.
1.CookieからセッションIDを取得する
HTTPProcessorは、ユーザの要求ごとにユーザの要求を解析し、HTTP要求ヘッダを解析し、jsessionidのようなクッキーが存在することを発見した場合、クッキー値をHttpSevletRequestオブジェクトにセットする
if (name.equals("cookie")) {
   Cookie cookies[] = RequestUtil.parseCookieHeader(value);
   for (int i = 0; i < cookies.length; i++) {
      if (cookies[i].getName().equals("jsessionid")) {
         // Override anything requested in the URL
         if (!request.isRequestedSessionIdFromCookie()) {
            // Accept only the first session id cookie
            request.setRequestedSessionId(cookies[i].getValue());
            request.setRequestedSessionCookie(true);
            request.setRequestedSessionURL(false);
         }
      }
      request.addCookie(cookies[i]);
   }
}

2.セッションを取得し、存在しない場合は新規セッションを作成
Sessionを使用してコンテンツにアクセスする必要がある場合は、RequestのgetSessionメソッドが呼び出されます.
private HttpSession doGetSession(boolean create) {
        // There cannot be a session if no context has been assigned yet
        if (context == null)
            return (null);

        // Return the current session if it exists and is valid
        if ((session != null) && !session.isValid())
            session = null;
        if (session != null)
            return (session.getSession());

        // Return the requested session if it exists and is valid
        Manager manager = null;
        if (context != null)
            manager = context.getManager();

        if (manager == null)
            return (null);      // Sessions are not supported

        if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId);
            } catch (IOException e) {
                session = null;
            }
            if ((session != null) && !session.isValid())
                session = null;
            if (session != null) {
                return (session.getSession());
            }
        }

        // Create a new session if requested and the response is not committed
        if (!create)
            return (null);
        if ((context != null) && (response != null) &&
            context.getCookies() &&
            response.getResponse().isCommitted()) {
            throw new IllegalStateException
              (sm.getString("httpRequestBase.createCommitted"));
        }

        session = manager.createSession();
        if (session != null)
            return (session.getSession());
        else
            return (null);

}

簡単に言えば、前にSessionIdが設定されている場合、requestはマネージャでSessionを探し、ある場合はそのまま使用し、存在しない場合はマネージャにSessionを作成させます.
追加する必要があります.Tomcatのセッションの作成とメンテナンスは、StandardManagerが標準的なインプリメンテーションであるマネージャインタフェースを実装することによって実現されます.もちろん、クラスタTomcatなどの異なるアプリケーションシーンに対して、セッションは各サーバで共有する必要があります.また、異なるマネージャを使用してセッションのメンテナンスを実現する必要があります.
3.Sessionが存在する場合、ResponseでHTTPResponseBaseでSetCookieを設定するSetHeaderメソッドでは、RequestでSessionオブジェクトが存在するかどうかをチェックし、存在する場合はSessionIdをSet-Cookieヘッダに書く
if ((session != null) && session.isNew() && (getContext() != null) && getContext().getCookies()) {
	Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getId());
	cookie.setMaxAge(-1);
	String contextPath = null;
	if (context != null)
	    contextPath = context.getPath();
	if ((contextPath != null) && (contextPath.length() > 0))
	    cookie.setPath(contextPath);
	else
	    cookie.setPath("/");
	if (hreq.isSecure())
		cookie.setSecure(true);
	addCookie(cookie);
}

	// Send all specified cookies (if any)
synchronized (cookies) {
	Iterator items = cookies.iterator();
	while (items.hasNext()) {
		Cookie cookie = (Cookie) items.next();
		outputWriter.print(CookieTools.getCookieHeaderName(cookie));
		outputWriter.print(": ");
		outputWriter.print(CookieTools.getCookieHeaderValue(cookie));
		outputWriter.print("\r
"); } }

実は
SESSION_COOKIE_NAME

JESSIONIDですが、tomcatがなぜこの文字列を使うのかは、tomcatを開発したプログラマーと検討するかもしれませんが、実は彼女はどんな名前を呼ぶことができます.Cookieを設定するときにCookieToolsがあることに気づきました.HTTPバージョン番号に基づいて、Set-CookieかSet-Cookie 2かを決定するgetCookieHeaderNameの方法
public static String getCookieHeaderName(Cookie cookie) {
    int version = cookie.getVersion();

    if (version == 1) {
        return "Set-Cookie2";
    } else {
        return "Set-Cookie";
    }
}

 4. ブラウザ検証
まずサーバに初めてリクエストしましたが、ブラウザから送信されたデータは以下の通りです.
ブラウザから送信されたCookieにはJESSIONIDが存在しないため,セッションはまだ作成・維持されていないことがわかる.
しかし、サーバーのResponseでSet-Cookieの最初の部分が表示されると、サーバーはセッションを確立し、唯一の表示を割り当て、ブラウザに「今度誰だか教えてください」と伝えます.
次にブラウザを使って、再びサーバーを要求すると、Requestは以下のように見えます.今回のアクセスCookieにはJESSIONIDが追加されており、サーバーはこのSessionIDを利用して、ローカルからSessionオブジェクトを見つけ、記録されたユーザーの行為やユーザー情報を手に入れることができます.