セッション

actix-web にはセッションのプラグインがあります。 actix-web のサイトではクッキーにセッションの内容を保存するタイプのみ紹介されていますが、Redisを使用する場合のサンプルも実装されています。 ただ、下記の問題がありました。

  • ロックしていない
  • TTLの更新が毎回か、更新があったときのみ

1つ目のロックしていない問題について、PHPでは初期の頃からセッションの排他ロックがありました。 ほぼ1ページが1アクセスの時代から排他ロックがあったのですが、現在では1ページの表示にAjaxで複数回APIを呼び出すことが多く、セッションの排他処理がないとタイミング依存の不具合が発生する可能性があります。

2つ目のTTLの更新については、更新があったときのみのTTL延長では操作中に突然ログアウトしてしまう可能性がありますので、アクセスごとに毎回TTL更新する必要があります。ただ、より効率的な運用としては10分毎に1回などのほうがセッションタイムアウトまでの時間もほとんど影響がなく、サーバの負荷を下げることが出来ます。

SenaXではキャッシュを使用することによって非常に高速に動作し、上記の問題を解決したセッションを提供します。

  • 排他ロックではなくCAS(Compare-and-Swap)を採用
  • TTLの更新はTTL期間の1/64の時間経過後のアクセスで更新

また、セッションの記録領域を base, login, debug の3種類に分けています。 ログアウトしたときにセッション情報を破棄することがありますが、破棄する情報か否かをログアウト処理に個別に実装するのはあまりスマートではありませんので、ログインしている間だけ有効でログアウト時に破棄するデータを login 領域に保存してログアウト時にまとめて破棄を可能にし、破棄しない情報を base 領域に保存して破棄されないようにします。 debug 領域は devプロファイルでのみ有効で、releaseプロファイルでは保存されず、参照は常に空になりますので、無駄な処理が実行されることがありません。

次にセッションをDBに保存するとテーブルにユーザIDのカラムを追加しがちですが、ユーザIDのカラムが必要になりそうな機能の代替実装方法について説明します。

  • 複数セッション同時アクセス禁止 複数セッション同時アクセス禁止は、複数のユーザが同一アカウントを流用することによりライセンスに違反して利用できることを防ぐために行われます。 実装としては、ユーザテーブルなどユーザIDが主キーのテーブルに現在ログインしているセッションIDを保存し、有効なセッションであることを確認するようにします。

  • 他のセッション無効化 不正アクセスの疑いがある場合などにパスワード更新のタイミングで他のセッション無効化をすることがあります。 実装としては、パスワードにバージョンをつけ、セッションにログイン時のパスワードのバージョンを保存し、アクセスのたびにチェックしてバージョンが変更されていないか確認します。 また、何らかの事情でユーザのアクセス権限を剥奪する可能性がありますので、ユーザアカウントの有効性チェックはアクセスのたびに行うことが望ましいです。