Webアプリのセッション管理とデータ保存を学ぶ#1(社内勉強会)

#1 Webアプリのセッション管理の基礎(本記事) #2 クライアント側のデータ保存方法 #3 サーバー側のデータ保存方法 概要 本記事はWebアプリの開発初心者、または書いたことはあるけどサーバーやインフラについてはよく分かっていない人向けです。 Webアプリを「データや状態の保存」という観点からクライアント側とサーバー側について説明します。 1. Webアプリのセッション管理の基礎 HTTPプロトコルはステートレスなので、そのままではデータや状態を次のHTTPセッションに引き継げません。このままでは掲示板や商品購入や支払い機能を作れないので、何らかの形で状態を維持するしくみが必要です。 moirmorihoge注) ステートレスとステートフルの違いについては以前の記事を先に読んでおくと良いでしょう。 Webアプリの基礎とさまざまな実行環境を理解する#3(社内勉強会) — 補講 Webサービスを構成する上でのステート(State: 状態)管理機能には、以下の要件が求められます。 HTTPリクエストを受け取ったときに、同じユーザーからのアクセスを「これは以前のこのリクエストと同じ一連のアクセスである」と判別する必要があります。これができないとログイン状態を保持するといったことができません。 また、ユーザーごとにステートを分けて管理することが求められます。同じ「マイページ」のURLにアクセスしていても、Aさんの「マイページ」とBさんの「マイページ」はログインしているユーザーによって異なるものが表示されるのが一般的です。 ※もちろんAさんでログインしていたのにリロードするたびにBさんの情報が見えたりするのもダメですね 最後に、これは必須ではありませんが、ステートを保持したうえで、ステートに保存された情報はなるべく少なくしたいというのがあります。ログイン済みのHTTPリクエストの度にユーザーIDとパスワードを毎回送ったり、ショッピングカートに入れた注文情報を都度送るというのはできなくはないですが、サーバー側のデータが変わらないのであれば毎回クライアントーサーバ間で受け渡しをするのはオーバーヘッドが大きいですしね。 HTTPプロトコルでは状態を「ステート」という用語で表していますが、Webページの場合はステートを「セッション」と呼び、ステート管理を「セッション管理」と呼びますので、以後この呼び方で統一します。 そこで、Webサービスでは何らかの形で「セッションID」というものをユーザーごとに持たせ、これを頼りにセッションを管理するという戦略を取ります。 静的Webサービスのように、常にWebサーバーがアクセス元に関係なく同じレスポンスを返すような状態のないWebサービスであればセッションを管理しなくても成立しますが、ほとんどの場合はセッション管理を行います。 morimorihoge注) カタログサイト(注文処理を含まない)などではセッション不要な例もありますが、「お気に入り」機能や「閲覧履歴」みたいなものを出そうとすると結局セッション管理が必要になってくることもよくあります。 ※もっとも、この程度であればCookieにデータを格納するという手もあります Webサービスでは、何らかの形でセッションIDというものをユーザーごとに持たせるという考え方でセッション管理を行います。ユーザーからのHTTPリクエストに含まれるセッションIDが同じであれば、同じユーザーからのリクエストであるとみなします。 セッションIDの具体的な管理方法の種類について、次で説明します。 セッション管理の手法 Webサービスにおけるセッション管理の手法はいくつかあります。現在主流なのは2. のCookieを使う方法です(上の図でも既にCookieを使う例で説明しています)。 A. GET/POSTリクエストパラメータ GET/POSTリクエストパラメータ(クエリパラメータとも呼ばれます)はセッションIDをリクエストURIのパラメータの一部に含める方式です。URIで?で始まる長めのパラメータが付いているのを見たことのある人も多いと思います。 この方式はどのブラウザでも確実に使えます。その昔のガラケーはCookieが使えない時代があったため、ガラケー対策として使われていました。 その代り、すべてのGETリクエストのパラメータに明示的にセッションIDを付けないとセッションを維持できません。したがって、GETリクエストのURIにセッションIDが常に丸見えになってしまいます。 morimorihoge注) この手法はユーザー登録時のメールアドレス認証などのごく限られた場合を除き、現在推奨されません。 特に危険なのは検索エンジンのクローラがセッションID付きのURLをキャッシュしてしまった場合で、正しくセッションIDのリセット処理を行っていない場合には最悪一部のユーザーの情報漏洩に繋がる可能性があります。 また、サイトを見ているユーザーが友人や同僚に今見ているページのURLを共有しただけでもセッションIDが漏洩してしまう可能性があります。 レガシーシステムとの統合等でどうしても使わざるを得ない場合には、IPアドレス制限やBasic認証などの他の認証方式も併用するのが安全(まだマシという程度)でしょう。 B. Cookie Railsも含めて現在最も一般的に使われているのが、Cookieによるセッション管理です。CookieはサーバーはHTTPリクエストの中(Cookieヘッダ)から、ブラウザであればJavaScriptから読み書きできます。 Cookieを使う場合、GET/POSTパラメータ方式とは異なり一般的なHTTPサーバーのログには記録されないことや、一度生成されたセッションIDの破棄タイミングなどをHTTPのCookie機能(expires値など)を使って管理することができる利点があります。 morimorihoge注) Cookie中のデータはHTTPリクエストに含まれているので、中間にあるProxyサーバーやネットワーク上に悪意のあるホストがいる場合には覗き見ることは可能です。 Cookieに機密情報を含めてやり取りしたい場合には、SSL/TLSを使ったHTTPS通信で行うようにしましょう。 また、言うまでもない話ですがCookieの内容はクライアント側が常に任意に読み書き可能なので、ログインセッションなどの重要な情報を扱う場合には、暗号化したり署名を付けるなどの方法で改竄を防止するといった対策を行うのが一般的です。 C. その他 上の2つの代表的なセッション管理方法以外にも次の方法があります。 クライアント証明書型は、クライアント証明書に含まれるユーザ情報をセッションID(ログイン情報)として使います。 ユーザー発行型は、セッションIDをユーザー側(ブラウザのJavaScriptなど)で作成するもので、送受信そのものは上述のCookieやリクエストパラメータを使います。 #1 Webアプリのセッション管理の基礎(本記事) #2 クライアント側のデータ保存方法 #3 サーバー側のデータ保存方法 関連記事 Webアプリの基礎とさまざまな実行環境を理解する#1(社内勉強会) Linuxのサービス起動周りとDockerとの関連を理解する#1(社内勉強会)