2

次の単純化されたシナリオを検討してください。

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }

    // restricted
    public string SocialSecurityNumber { get; set; }

    // restricted
    public string MothersMaidenName { get; set; }
}

したがって、アプリケーションでは、多くのユーザーがPersonデータを表示できます。一部のユーザーはすべてを表示できます。他のユーザーは と のみNameを表示できますAge

UI に許可されたデータのみを表示することは、クライアント側では十分に簡単ですが、そのデータをクライアントに送信することさえ本当にしたくありません。

私はこれを達成するために、FullPerson : BasicPerson階層 (table-per-class-hierarchy) を作成しようとしました。目的の型を取得するために a の 2 つの実装を使用StaffRepositoryしましたが、NH プロキシが原因で実行時に必要なキャストが失敗します。もちろん、RDBMS では、テーブル内の任意の行がaまたは aPeopleを表すことができ、両方に同じ識別子値を指定しても機能しません。FullPersonBasicPerson

マッピングのみを検討し、結果トランスフォーマーをFullPerson使用して にフィルターダウンすることを検討しましたが、これは一方通行であることを理解していますが、エンティティ管理と遅延読み込みの利点を最大限に活用したい (上記の例にはコレクションは含まれていません)。セッション。AliasToBeanBasicPerson

もう 1 つの考えは、制限されたすべてのフィールドをクラスにまとめて、これをプロパティとして追加することでした。このアプローチに関する私の懸念はいくつかあります。

  1. それは私のドメインモデルを危険にさらし、
  2. 遅延ロードするには、プロパティをコレクション (常に 1) として宣言する必要があります。
  3. その怠惰なコレクションが読み込まれないようにする方法もわかりません。

これはすべて間違っていると感じます。望ましい結果を達成するための既知のアプローチはありますか?

説明:

これはイントラネット専用のデスクトップ アプリケーションです。セッションはクライアント上にあります。確かに中間サービス層を作成することはできますが、遅延読み込みと変更追跡を断念する必要があり、それを維持したいと考えています。

4

2 に答える 2

2

ドメイン モデルはそのままにし、代わりにAutomapperを使用して、現在のユーザーのセキュリティ レベル (または特定のプロパティへのアクセスを決定するために使用する基準) に基づいて特定の DTO にマップします。これは、UI とリポジトリの間に位置するある種のサービス レイヤーで行う必要があります。

編集:

遅延読み込みと変更追跡を維持するという要件に基づいて、おそらくプロキシ パターンを使用してドメイン オブジェクトをラップすることは実行可能な代替手段でしょうか? 元のドメイン モデルを、指定された各プロパティでセキュリティ チェックを実行するプロキシでラップすることができます。CSLA.NETはフィールド レベルのセキュリティにこのような方法を使用していると思います。おそらく、これをさらに一歩進めて、ユーザーがアクセスできるプロパティのみを公開するプロキシによって実装されたインターフェイスを使用できます。

于 2010-09-07T17:40:43.500 に答える
2

最初に、セキュリティを処理するのは NHibernate の責任であり、それに基づくデータのリダクションではないと思います。データアクセスレイヤーに入れようとして、これを過度に複雑にしていると思います。

クライアント (リポジトリ自体ではないはず) からこのデータ要求を受け取るサービスまたはコントローラーにレイヤーを挿入し、ユーザーのアクセス許可に基づいてデータのリダクションを実行します。したがって、DB に対して完全なクエリを実行すると、ユーザーのアクセス許可に基づいて、サービス レイヤーが結果セットのフィールドをクリアしてから、サービス接続を介してその結果セットを返します。これは絶対的に最もパフォーマンスの高いソリューションではありませんが、すべてのデータをクライアントに送信してクライアント ソフトウェアで「検閲」するよりも安全であり、パフォーマンスも優れています。サーバー アーキテクチャの DB とサービス レイヤー間のイーサネット接続は、サービス レイヤーとクライアント間のインターネット接続よりもはるかに多くの帯域幅を処理できます。また、リモート クライアント アプリでは、通常、クライアントがデータをどのように処理するかをほとんど制御できません。あなたのソフトウェアのハッキングされたコピー、またはユーザー セキュリティについて 2 つのフリップを提供しない類似のソフトウェアと話している可能性があります。

サービスと DB の間のネットワーク帯域幅が非常に重要な場合、または多くの情報が制限されている場合、Linq2NH は、選択リストを使用してクエリ結果に含める必要があるものと含めないものを指定できるほどスマートである必要があります。

if(!user.CanSeeRestrictedFields)
   var results = from p as Repository.AsQueryable<Person>()
   //rest of Linq statement
   select new Person { 
         Name = p.Name,
         Age = p.Age
      };
else
   var results = from p as Repository.AsQueryable<Person>()
   //rest of Linq statement
   select new Person { 
         Name = p.Name,
         Age = p.Age,
         SocialSecurityNumber = p.SocialSecurityNumber,
         MothersMaidenName = p.MothersMaidenName
      };

Linq2NH が条件演算子を SQL に解析できるほど賢いかどうかはわかりません。私はそれを疑いますが、可能性は低いですが、ユーザーがそれらを見る権利を持っているかどうかに基づいて、SSN フィールドと MMN フィールドの初期化子で条件演算子を指定して、これら 2 つのクエリを組み合わせることができます。

于 2010-09-07T17:47:21.440 に答える