読者です 読者をやめる 読者になる 読者になる

好みのセッション ID を利用する

昨日はセッション状態を Memcached に格納しましたが、次はセッション ID を好みの形に変えてみます。

実装

セッション ID を任意の値にするには ISessionIDManager インタフェースを実装したカスタムマネージャクラスを作成します。

作成しますが…実は、セッション ID の既定の実装である SessionIDManager クラスを継承して、CreateSessionID メソッドと Validate メソッドをオーバーライドするだけでもいけます。

めっちゃ簡単なので、クッキーレスな環境でもセッションを使えるようにする必要がなければ後者をオススメします。

※追記:クッキーレス環境でも、独自セッション ID を使いたいだけであれば後者で問題無いです。 URL への差し込み方(既定では(S(SessionID)))を変えたかったり、独自エンコーディングを使いたい時に前者を使って下さい。

実装はこんな感じで。

public class CustomSessionIDManager : SessionIDManager
{
    public override string CreateSessionID(HttpContext context)
    {
        return "my-session-id";
    }

    public override bool Validate(string id)
    {
        if (string.IsNullOrEmpty(id))
            return false;

        return id == "my-session-id";
    }
}

ここではベタで書いてしまっていますが、実際は CreateSessionID メソッドに各自お好きなセッション ID 生成処理を書いて下さい。

そして、Web.Config に以下を追加します。

<sessionState sessionIDManagerType="namespace.classname,assemblyname"></sessionState>

これだけです。簡単ですね-。

既定のセッション ID について

セッション ID の採番処理を自分で作る場合、当然ですが、有効なセッション ID が衝突しないよう作り込まないといけません。で、まぁ無難なところで GUID 使えば良いと思うんですが、そもそも既定のセッション ID はどうしてんのかなーと思って調べみたんですが

ASP.NET でセッション ID が再利用されるしくみと理由について

セッション ID は、20 文字の文字列で表される 120 ビットの乱数値です。

SessionIDManager クラス

ASP.NET セッション識別子は、ランダムに生成された数を小文字の a ~ z と数字の 0 ~ 5 のから成る 24 文字の文字列にエンコードしたものです。

これどっちが正しいんでしょうね。

前者の20文字で120ビットってことは、1文字当り6ビットですね。Base64 で使われる文字群のことでしょうか。もしどっちも正しいと考えるなら、Base64 で使われる文字群からランダムな20文字の文字列を作って、それを更にエンコードしてるってことですかね。なんかそれ無理あるなぁ。

実際にクッキーに保存されるセッション ID を見ると24文字なので、少なくとも後者は間違いではないと思ってますが、前者の情報をどう解釈すべきなんだろう。

※追記

ILSpy を使って既定の SessionIDManager の実装を調べてみたところ、 ネイティブで実装されたバイト配列生成 API から 15byte のランダムなバイト配列を生成し、それを

小文字の a ~ z と数字の 0 ~ 5 のから成る 24 文字の文字列

エンコードしていることが分かりました。

エンコード自体は特別なアルゴリズムではなく、バイト配列から 5bit ずつ抜き出した値を a から 5 までの 31 文字に順番にマッピングしているだけのようですね。

問題無いのか分からなかったので確認したソースを載せることはしませんが、興味のある方は ILSpy などのデコンパイラで確認してみてください。