
- バックエンドは単一のサーバーに収まらず、すべてのバックエンドサーバーに共通のセッションストレージを必要とします
- さまざまな理由により、組み込みのファイルセッションの速度の調整を中止します
従来、このような場合、Redis、Memcached、またはその他の外部ストレージがユーザーセッションの保存に使用されていました。 その結果、データベースの運用負担が発生しますが、これはシステムの単一障害点やボトルネックではありません。
ただし、このアプローチに代わるものがあります。 セッションデータが暗号署名で認証されている場合、ユーザー自身のブラウザCookieにセッションデータを安全かつ安全に保存することができます。 これに加えて、データも暗号化されている場合、ユーザーはセッションのコンテンツを利用できません。 この保存方法の主な利点は、セッションに集中型データベースが必要ないことです。これにより、信頼性、速度、およびスケーリングという形で生じるすべての利点が得られます。
メカニズムの説明
このアイデアは新しいものではなく、さまざまなプログラミング言語の多くのフレームワークとライブラリに実装されています。 次に例を示します。
Ruby on Railsでは、セッションを格納する他のすべての方法と比較して、このメカニズムのパフォーマンスに大きな賭けをし、デフォルトで使用することに注意する価値があります。
利用可能な実装のほとんどは次のように機能します。セッションの有効期限、セッションデータ、および有効期限とデータのHMAC署名を含む文字列をCookieに書き込みます。 クライアントの要求に応じて、Cookieは適切なハンドラーによって読み取られ、署名が検証され、現在の時間がセッションの有効期限と比較されます。 すべてが一致した場合、ハンドラーはセッションデータをアプリケーションに返します。
ただし、このメカニズムの一般的な実装では、Cookieは暗号化されません。
従来のアプローチとの比較
その結果、Cookieにセッションを保存することには次の利点があります。
- Webアプリケーションのパフォーマンスが向上している理由は、小さな暗号化操作が、セッションデータを抽出するためのネットワーク交換セッションまたはディスクアクセスよりも安価であるためです。
- Webアプリケーションは外部KVストレージに依存しないため、Webアプリケーションの信頼性が向上します。 セッションリポジトリにフォールトトレランスが備わっていても、絶対的な安定性は得られません。切り替えには時間がかかり、問題の一部(リージョン間のネットワーク接続性の低下など)は完全に根絶することはできません。 多くの場合、セッションは単一のサーバーに保存されます。これは、Webアプリケーション全体の単一障害点です。
- リソースを節約します。 セッションを保存する必要がなくなります。つまり、ディスクアクティビティが減少した小規模サイトの所有者はこの恩恵を受け、大規模なWebプロジェクトの所有者は複数のサーバーを解放します。
欠点もありますが、それらがない場合:
- クライアントによって送信されるデータの量が増加します
- Cookieのサイズには制限があるため、セッション内のデータのサイズには制限があります。 通常、これはエンコードされたデータの4 KBよりわずかに少ないです。
- クライアントは、セッション状態を以前に発行および署名された値にロールバックできます。その値の暗号署名は現在でも有効です。
PHPの実装
PHPに似たものを見つけようとしたときに、最小要件に達するライブラリが1つもないことに驚いた。
- セキュリティ:暗号化エラーなし
- 実際のコードベース:最新バージョンのPHPのサポート、依存関係に非推奨の拡張機能がない(mcryptなど)
- テストの可用性:セッションは基本的なメカニズムの1つであり、未熟なコードは実際のアプリケーションの中心では使用できません
さらに、私はそれをまったく不要ではないと考えます:
- 暗号化機能:クライアントが読み取るクライアント上のオープンセッションストレージは、全員に適しているわけではありません。
- 最もコンパクトなデータ表現-オーバーヘッドとセッション容量のマージンを最小限に抑えるため
- SessionHandlerInterfaceによる埋め込み可能性
私がレビューした実装は次のとおりです。
リポジトリ | 解説 |
---|---|
github.com/Coercive/Cookie | 実際、セッションを操作するためのライブラリではありません。 暗号化されたCookieに署名せずに入れます。 |
github.com/stevencorona/SessionHandlerCookie | 要件に最も近いが、依然として重大な欠点があります。
|
github.com/mapkyca/Encrypted-Client-Side-Sessions |
|
また、Slimバージョン2.xフレームワークのCookieにセッションを保存する実装も見ましたが、そこには署名も暗号化もありません。 著者がすぐに警告するもの。
署名の代わりに署名の検証と暗号化が重要なのはなぜですか? まず、特にセッションレコードが短いセッションでは、ガベージを含むCookieが復号化される可能性が顕著にあります。 第二に、セッションのある回線はデシリアライズされ、信頼できないソースからの回線はデシリアライザーの入力に送信できません。
すべての検索の後、私はそのようなライブラリを自分で実装することにしました。
独自の実装
Packagist: packagist.org/packages/snawoot/php-storageless-sessions
Github: github.com/Snawoot/php-storageless-sessions
composerからのインストール:
composer require snawoot/php-storageless-sessions
主な機能:
- 必須の暗号化。 アルゴリズムとモード-選択する対称暗号。OpenSSLで利用可能。 デフォルト:AES-256-CTR。
- 暗号化拡張ハッシュの範囲から選択する任意のハッシュアルゴリズムを使用したCookieのHMAC署名。 また、派生暗号キーの生成にも使用されます。 デフォルト:SHA-256。
- タイムアタック対策を実施
- メインデータセットと有効期限に加えて、セッションIDも署名でカバーされます。これにより、セッションデータを外部データとリンクする余地が残ります。
- 実装は、SessionHandlerInterfaceと互換性のあるクラスとして提示されます。つまり、ほぼすべてのPHPアプリケーションで透過的に使用できます。
- 暗号化と署名によってもたらされるストレージのオーバーヘッドは最小限です。
暗号化モードの選択に関するいくつかの言葉。 ブロック暗号化モード(ECB、CBC)を使用すると、暗号文の長さがわずかに長くなります。 これは、元のメッセージの長さがブロックのサイズの倍数でなければならないためです。 必須のパディングのため、長さの増加は1バイトから暗号ブロックのサイズまでです。 つまり、AESの場合は1〜16バイトです。 ストリーム暗号化モード(OFB、CFB、CTRなど)を使用する場合、元のメッセージはブロック暗号を通過せず、代わりにブロック暗号を使用してガンマシーケンスを形成し、暗号テキストの長さが元のメッセージの長さと正確に一致します。タスク。
使用例
このハンドラーを使用する方法を示す小さなスクリプト:
<?php require_once("vendor/autoload.php"); header('Content-Type: text/plain'); $secret = '********************'; $handler = new VladislavYarmak\StoragelessSession\CryptoCookieSessionHandler($secret); session_set_save_handler($handler, true); session_start(); if ($_GET) { foreach ($_GET as $key => $value) $_SESSION[$key] = $value; echo "Updated session:"; } else echo "Current session data:\n"; var_dump($_SESSION);
https://vm-0.com/sess.phpのクエリ行で異なるセッション値を設定することにより、その動作を観察できます 。
symfony統合の例:
framework: session: handler_id: session.handler.cookie services: session.handler.cookie: class: VladislavYarmak\StoragelessSession\CryptoCookieSessionHandler public: true arguments: ['reallylongsecretplease']
実際のデモとして、私はこのセッションハンドラーを、セッションを使用することを思いついた最初のWebアプリケーションに接続しました。 DokuWiki: wiki.vm-0.comであることが判明しました。 サイトには登録とログインがあり、セッションの作業はCookieで確認できます。
ご清聴ありがとうございました。この記事がプロジェクトの発展に役立つことを願っています。