コンテンツへスキップ
DedicatedPHP 接触

PHPバックオフィスで安全な検索を設計する方法

PHPで担当者が権限の範囲を超えてデータを漏らさずにレコードを検索できるよう、フィルター、権限、クエリ、テストを設計します。

検証済みフィルターとレコード単位の権限を組み合わせたPHP管理検索の図

有用な管理検索とは、すべてのユーザーがテーブルのあらゆる項目を検索できるようにすることではありません。具体的な運用タスクを完了できるよう支援しながら、各ユーザーが閲覧できるレコードの範囲を守る必要があります。PHPアプリケーションでは、この区別をサーバー側で設け、バックオフィスの画面だけでなく、情報を返すすべてのルートに適用しなければなりません。

PHPバックオフィスで安全な検索を設計するには、検索の定義、許可する条件、アクセス範囲の算出方法、データベースを保護する制限を合意する必要があります。これらの基準は、単純なSQLクエリにも、検索インデックスを利用するシステムにも適用できます。

タスクとアクセス範囲から始める

タスクとアクセス範囲から始める — guía visual de DedicatedPHP

検索対象の項目や技術を選ぶ前に、検索で解決すべきタスクを特定します。たとえば、注文番号で注文を探す、メールアドレスでアカウントを見つける、ステータスでインシデントを確認するといったタスクです。各タスクについて、実行するユーザーと検索できるレコードを記録します。対象範囲を「テーブルにあるすべてのデータ」と定義するのは避けましょう。たとえばサポート担当者が一部の顧客にアクセスする必要がある一方、管理者が操作できる対象は別の集合である場合があります。

これらのルールを、組織、チーム、所有者、地域、その他ドメイン内の関係に基づく、理解しやすい認可モデルに落とし込みます。また、アクセス権が時間とともに変わるか、ユーザーがセッションを開いたまま権限を失った場合にどうするかも決めます。画面上で選択肢を非表示にすることはできますが、実際のルールはサーバー側で検証しなければなりません。

明示的なフィルターを定義し、各条件を検証する

検索可能な項目とフィルターの種類を限定して設計します。たとえば、画面では注文番号の完全一致、一覧から選ぶステータス、日付範囲を指定できるようにします。クライアントから送信された任意のパラメーターを、列、SQL条件、アクセス条件として扱ってはいけません。

値はサーバー側で検証します。形式、長さ、範囲、許可された値、組み合わせを確認してください。プリペアドクエリを使い、値とSQL文を分離します。ただし、プリペアドパラメーターだけでは動的な列名や並び順は保護されません。これらには、サーバー側で定義した許可リストを使う必要があります。

業務上のフィルターと認可条件は別物です。ユーザーは「保留中のステータス」を指定できますが、組織IDを送信してアクセス範囲を広げることはできてはなりません。フォームで編集できる項目を信頼せず、認証済みユーザーの識別情報と有効なルールに基づいてアクセス範囲を算出します。

行、件数、関連アクションにも認可を適用する

アクセス条件は、結果を取得するクエリに含めます。レコードを先に取得してからPHPで絞り込むと、ログ、メモリ、レスポンス、補助ルートからデータが漏れるおそれがあります。また、ページネーションや件数計算も複雑になります。可能な限り、認可条件と検索フィルターを同時に適用したクエリを構築してください。

関連するすべての出力を確認します。検索結果の合計件数から、認可範囲外のレコード数が分かる場合があります。自動候補表示から名前やメールアドレスが漏れることもあり、エクスポートと画面で異なるルールが適用される可能性もあります。詳細ページへのリンクや一括操作にも、同じアクセス範囲を適用してください。アクセス不能なレコードが存在するかどうかも機密情報である場合、それを推測できるようなレスポンスの違いを避けます。

一貫性を保つうえで有効なら、アクセス条件の構築を共通化します。ただし、共通の抽象化を自動的な認可と混同してはいけません。各クエリとエンドポイントが正しく利用していることを確認してください。

SQLと検索インデックスを選ぶ

フィルターが明確で、複雑なテキスト関連度が不要であり、適切なインデックスによってデータベースがクエリを処理できるなら、SQLで十分なことが多いでしょう。等価条件、範囲、リレーション、許可された並び替えを組み合わせる直接的な方法です。別のコンポーネントを追加する前に、実行計画とインデックスを確認してください。

SQLでは必要な運用目標を満たせない場合、入力ミスへの許容、言語解析、テキスト関連度、大量データの検索に検索インデックスが役立つことがあります。ただし、同期、更新の遅延、アクセス制御、追加の運用が必要になります。権限の正しい情報源として、データベースに代わるものではありません。

インデックスに複数のアクセス範囲のデータが含まれる場合は、ドキュメントを返す前に認可条件でクエリを制限し、権限の変更や取り消しがどのように反映されるかを検討してください。機密性の高い操作では、正しい情報源に照らしてアクセス権を再検証します。許容できる遅延と、インデックスが古い場合や利用できない場合の動作を定義してください。代替策として高度な検索を一時的に無効にすることはできますが、制御を省略してはいけません。

コスト、並び替え、レスポンス量を制限する

1ページあたりのレコード数に上限を設け、安定したページネーションを適用します。大量のデータや頻繁に変化する結果では、カーソルベースのページネーションにより、行のずれに関する問題の一部を回避できる場合があります。ただし、一貫した並び順と明確な継続条件が必要です。

並び替えは想定した項目だけに許可し、一意のIDなどによる決定的な副次ソートを設定します。テキスト検索の長さ、期間、フィルター数に上限を設け、コストの高い走査を引き起こす空検索は避けてください。負荷の高い処理には、レート制限や最大実行時間を検討します。画面で不要な項目を検索結果に含めるべきではありません。

権限と境界ケースをテストする

異なるユーザープロファイルとアクセス範囲について、許可・拒否の両方のテストを用意します。各ユーザーが許可されたレコードを検索でき、フィルター、ページネーション、並び替えを変えたり、詳細ページを要求したりしても、他のレコードを取得できないことを確認してください。フィルターの組み合わせ、不正な値、結果が空の場合、所有者やアクセス範囲が変わったレコードもテストに含めます。

件数、候補表示、エクスポート、一括操作もテストします。有効なテストでは、他者のレコードが一覧に表示されないだけでなく、番号の完全一致で検索できず、補助レスポンスからも推測できないことを確認します。権限が変わったとき、定めたポリシーに従って動作が更新されることも検証してください。

運用メトリクスは、別の情報漏えいを招かずに診断に役立つものでなければなりません。レイテンシ、エラー、結果件数、操作の種類を記録し、機密性の高い検索語や不要な個人データは保存しないようにします。ログへのアクセスを制限し、保存期間を定めてください。低速クエリとインデックスのエラーを別々に監視し、性能の問題と認可の不具合を区別します。

変更を公開する前のチェックリスト

変更を公開する前のチェックリスト — guía visual de DedicatedPHP
  • タスク、ユーザープロファイル、アクセス範囲が文書化されている。
  • 検索可能な項目、フィルター、並び替え、制限が明示されている。
  • サーバーがパラメーターを検証し、クライアントのデータをアクセス許可に利用していない。
  • 結果、件数、候補表示、詳細、エクスポートに認可が適用されている。
  • SQLまたはインデックスに性能戦略があり、障害時の代替策がある。
  • 許可・拒否されるアクセス、権限変更、フィルターの組み合わせをテストしている。
  • 不要な機密検索語を保存せずに、ログとメトリクスから診断情報を得られる。

管理検索は、想定されたタスクを、理解しやすい結果、管理可能なコスト、検証可能なアクセス制限のもとで実行できるときに完成です。関連度の改善に検索対象データの拡大やインデックスの導入が必要なら、それを実装上の細部ではなく、セキュリティモデルの一部として評価してください。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る