セッションとセキュリティ
ドキュメントセッションとアクセス制御
Doconut トークンは強力です: それを提示した者は、オープンセッションにバインドされていなければ、ドキュメントのすべてのページを要求できてしまいます。このページでは、セッションが保持するもの、存続期間、そしてデフォルトで UseDoconut() が有効にするチェックについて説明します。
ドキュメントセッションが保持するもの
各成功した OpenDocumentAsync は、IMemoryCache に 1 つのセッションを作成します:
- ロードされたフォーマットビューア(解析されたドキュメントを保持するドキュメントエンジンインスタンス),
- ページごとの状態 — ウィジェットでユーザーが適用する回転、フリップ、注釈データ,
- 任意の 検索インデックス、最初の検索時に遅延構築されます(または、ページが共有ストレージから提供される際に事前構築された
.srhファイルからロードされます), DocOptions.Watermarkからのセッション ウォーターマーク.
有効期間
セッションは スライディングウィンドウ で期限切れになります: DocOptions.TimeOut 分(デフォルト 60)、トークンを提示するすべてのリクエストでリセットされます。セッションが期限切れまたは CloseDocument(token) によって追い出されると、その追い出しコールバックがドキュメントエンジンを破棄し、関連メモリを即座に解放します。
// 一回限りのプレビュー用の短命セッション
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });期限切れトークンでのリクエストは、Document session not found. Please re-open document. と表示されたエラー画像が返されます — クライアントは新しいトークンを取得するために再度開く必要があります。
組み込みトークンバインディング
UnsafeMode = false(デフォルト)を使用すると、OpenDocumentAsync は新しいトークンをそれを開いた HTTP リクエストの ASP.NET セッション にバインドし、secure-{token} マーカーをそのセッションに書き込みます。Doconut ミドルウェアはその後、他のブラウザセッションへのページ提供を拒否します:
- 盗まれたトークンを提示した別のブラウザ/セッション → エラー画像
You Are Not Authorized To View This Page. - セッションミドルウェアが登録されていない → HTTP 500
Session middleware not configured. Call UseSession() before UseDoconut().
これが、Quick Start が Doconut ブランチの前に AddSession() と app.UseSession() を必須とする理由です。実務上の 2 つの結果:
- クライアントはページリクエストに ASP.NET セッションクッキー を送信しなければなりません。クッキーを除去するクロスオリジン設定(またはクッキー保存がない API クライアント)はチェックに失敗します — これはバグではなく、機能が正しく動作していることを示します。
options.UnsafeMode = trueはバインディングを完全に無効にします。これは制御されたシナリオ向けに存在し、単一ノードの本番環境ではfalseのままにしてください。
綴りに注意してください。以前の .NET Standard ライブラリではこのプロパティは UnSafeMode
と呼ばれ、ミドルウェアに渡されていました;ここでは UnsafeMode で、AddDoconut() 内で一度だけ設定されます。
トークンバインディングはこのグローバル UnsafeMode スイッチだけで制御されます — デフォルトでオン(UnsafeMode = false)であり、すべてのセッションに適用されます。ドキュメント単位でのオプトアウトはありません;UnsafeMode = true を設定するとバインディングが全体で無効になります。
アクセス権限と認証ユーザー
UnsafeMode が false の場合、UseDoconut() はページミドルウェアの前にドキュメントアクセスミドルウェアを自動的に挿入します。二度登録しないでください。リクエストがトークンを持つと、ドキュメントが開かれたときに記録された アクセス権限 を検索し、以下すべてが成立する場合にのみ認可します:
- トークンに対する権限が存在する、
- それが期限切れでない(権限の有効期間 = ドキュメントの
TimeOut)、 - 要求元の ASP.NET セッション ID がドキュメントを開いたものと一致する、
- 開いた側が認証済みの場合、要求元ユーザーの
NameIdentifierクレームも一致する。
失敗時は 403 を返します — ページ/サムネイルリクエストの場合は PNG エラー画像として、その他はプレーンテキストとして。メッセージとトークンのクエリキーは DocumentSecurityOptions から取得されます(TokenQueryKey、デフォルト "token";UnauthorizedMessage、デフォルト "You Are Not Authorized To View This Page.")。アプリ構築前に ASP.NET Core DI を通じてこれらのオプションを設定してください。セッション状態が利用できない場合、ミドルウェアは HTTP 500 で閉鎖的に失敗します: ASP.NET Session is required for Doconut document security.
builder.Services.Configure<Doconut.Security.DocumentSecurityOptions>(options =>
{
options.TokenQueryKey = "token";
options.UnauthorizedMessage = "You Are Not Authorized To View This Page.";
});コアページミドルウェアはドキュメントを提供する前に secure-{token} セッションマーカーを検証します。UnsafeMode = true を使用すると、UseDoconut() はアクセスミドルウェアをスキップし、コアマーカーチェックも無効になります。
複数ノード間のセキュリティ
セッションバインドされたトークンは、ページを提供するノードがドキュメントを開いたリクエストも見たことがあることを前提としています。この前提は、複数のノードが共有ストレージから同じドキュメントを提供する場合には成立しません:ページリクエストが開くリクエストを見たことのないノードに届くことがあり、セッション単位のチェックで拒否されます。
答えはドキュメントを無防備にしないことです。AddDoconutDistributedDocumentSecurity(...) を通じて署名付きアクセスチケットを使用すると、セッションチェックが各ノードが独立して検証できる認証情報に置き換わります。完全な構成は 分散デプロイメント にあります。
失効
CloseDocument(token) はメモリを解放するだけでなく、secure-{token} マーカーを削除し、アクセス権限を失効させます。そのため、閉じられたトークンは両方のセキュリティ層で即座に無効になります。
本番環境チェックリスト
- 単一ノードで
UnsafeMode = false(デフォルト)を維持してください — このグローバルスイッチがトークンをセッションにバインドします。 AddDistributedMemoryCache()(MVC と Razor Pages アプリはすでに持っています)とAddSession()を登録し、Doconut ミドルウェアブランチの前にapp.UseSession()を呼び出してください。- セッションクッキーのポリシーがウィジェットのリクエストでクッキーを送信できるようにしてください(
SameSite、HTTPS)。 - ユーザーがドキュメントを離れる際に
CloseDocumentを使用してください — メモリとセキュリティの両方に効果があります。 - トークンをログに記録したり共有したりしないでください;短命の認証情報として扱ってください。
- 共有ストレージから提供していますか? 無防備なドキュメントを受け入れるのではなく、署名付きアクセスチケットに移行してください。
このページは役に立ちましたか?