atsukanrockのブログ

Microsoft系技術を中心にぼちぼち更新します

ASP.NETで「ログイン成功後に新しいセッションを開始」は可能なんだろうか?

はじめに

IPAが、『安全なウェブサイトの作り方』という、Webサイトのセキュリティに関するガイドブックを出している。このPDFの21ページに、「ログイン成功後に、新しくセッションを開始するようにする」という対策がある。この解説の内容は納得できるものだ。しかし、ASP.NETで、うまくこれを実装する方法はあるのだろうか?

新しくセッションを開始するには?

ASP.NETでセッションを新たに開始するようにするためには、HttpSessionState.Abandonメソッドを使うことになるはずだ。このメソッドによって、メソッドを呼び出した時点のセッションオブジェクトを破棄し、ASP.NETランタイムに、次の新しいセッションオブジェクトの生成を促す。

一般的なログインコード

上記PDFの指針に従うと、ログインが成功した際に新しいセッションを開始しなければならない。すると、一般的なログインコードは、次のようになるのではないか。

// ...ログイン処理...

if (<ログイン失敗>)
{
    return;
}

// (1) セッションオブジェクトを破棄
Session.Abandon();

// (2) ログインに関する情報をセッションオブジェクトに設定
Session["UserID"] = userID; // 例えばユーザーID

Abandonメソッドの仕様

ところで、Abandonメソッドのドキュメントをよく読むと、次の記述がある。

Abandon メソッドを呼び出すと、現在のセッションが無効になり、新しいセッションを開始できます。Abandon により End イベントが発生します。次の要求に対して Start イベントが発生します。

Abandonメソッドで破棄したセッションオブジェクトに代わる、次のセッションオブジェクトが生成されるのは、Abandonメソッドを呼び出したHTTPリクエストの、次回のHTTPリクエスト時だというのだ。

するとどうなるか

前述の一般的なログインコードは、期待通りに動作してくれるだろうか。上記のAbandonメソッドの仕様を見ると、そうは行かないことがわかる。なぜか。

ログインコードの(2)が問題だ。ログインに成功した場合、一般的にはそのログイン者に関する情報を、セッションオブジェクトに格納する。それをしているのが(2)だ。しかし、Abandonメソッドの仕様により、新たなセッションオブジェクトが生成されるのは、Abandonメソッドを呼び出した直後でなく、次回HTTPリクエスト時だ。つまり、Abandonメソッドを呼び出したHTTPリクエストの処理中に設定したセッション変数は、新たなセッションオブジェクトには引き継がれない。

Webアプリケーションでは一般的に、機密情報を格納するにはセッションオブジェクトを使う。前述のコードで言えばユーザーIDが機密情報だ。従って、ユーザーIDを格納する場所は、セッションオブジェクト以外には考えられない。私たちは、Abandonを呼び出したHTTPリクエストの処理完了時点から、次回HTTPリクエストの到着までの間、どこにユーザーIDを保持すれば良いのか。

誰か良い案ないですか?

というわけで、私は今のところ、「ログイン成功後に、新しくセッションを開始するようにする」を実装できていない。私は何か、簡単なことを見落としているのだろうか?誰か、良い案をお持ちか、または思いついた方、私にアドバイスをいただけませんか?