3

NHibernateを使用して特権を実装しようとしていますが、実行したいのは、Selectクエリがあるたびに、リターンタイプが何であるかを確認し、セキュリティが有効なタイプ(請求書など)の場合は制限を追加したいことです。 ICriteriaオブジェクトに対して、特定のレコードのみの取得を制限します(ユーザーがすべてを読み取ったか、自分の特権を読み取ったかによる)。

挿入と更新のためにこの種の特権を実装することができました

NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener

ただし、残念ながら、IPreLoadEventListenerデータベースが照会された後にが呼び出されます。したがって、フィルタリングはデータベースではなくコンピューター上でローカルに実行されるため、無駄になります。

NHibernateがクエリが実行される前に呼び出されるある種のイベントを提供するかどうか誰かが知っていますか?

4

2 に答える 2

2

使用できる場合は、Rhino.Securityを確認してください。まさにあなたがしようとしていることを実行します。それを使用できない場合でも、この問題の彼の実装を見ることができます。

于 2011-02-07T15:18:40.970 に答える
2

Filters を使用してこれを達成できませんか?

詳細はこちら

私のプロジェクトでは、これをインターセプターと組み合わせて使用​​しました。

各ユーザーがインスタンスを作成できるエンティティがいくつかありますが、それらを作成したユーザーのみがそれらのインスタンスを表示/変更できる必要があります。他のユーザーは、ユーザー X によって作成されたインスタンスを表示できません。

そのために、インターフェースを作成しましたIUserContextAware。「ユーザー コンテキストを認識する」エンティティは、このインターフェイスを実装します。

セッション ファクトリを構築するときに、必要なフィルターを作成しました。

 var currentUserFilterParametersType = new Dictionary<string, NHibernate.Type.IType> (1);
 currentUserFilterParametersType.Add (CurrentUserContextFilterParameter, NHibernateUtil.Guid);
 cfg.AddFilterDefinition (new FilterDefinition (CurrentUserContextFilter,
                                                           "(:{0} = UserId or UserId is null)".FormatString (CurrentUserContextFilterParameter),
                                                           currentUserFilterParametersType,
                                                           false));

これが完了したら、追加のフィルター基準を定義する必要がありました。

 foreach( var mapping in cfg.ClassMappings )
 {
    if( typeof (IUserContextAware).IsAssignableFrom (mapping.MappedClass) )
    {
       // The filter should define the names of the columns that are used in the DB, rather then propertynames.
      // Therefore, we need to have a look at the mapping information.

      Property userProperty = mapping.GetProperty ("UserId");

      foreach( Column c in userProperty.ColumnIterator )
      {
          string filterExpression = ":{0} = {1}";

          // When the BelongsToUser field is not mandatory, NULL should be taken into consideration as well.
          // (For instance: a PrestationGroup instance that is not User-bound (that can be used by any user), will have
          //  a NULL value in its BelongsToUser field).
          if( c.IsNullable )
          {
              filterExpression = filterExpression + " or {1} is null";
          }

          mapping.AddFilter (CurrentUserContextFilter, "(" + filterExpression.FormatString (CurrentUserContextFilterParameter, c.Name) + ")");
          break;
     }
 }

をインスタンス化するたびにISession、特定のインターセプターを使用する必要があることを指定します。

このインターセプターは、フィルターのパラメーターが設定されていることを確認します。

    internal class ContextAwareInterceptor : EmptyInterceptor
    {
        public override void SetSession( ISession session )
        {
            if( AppInstance.Current == null )
            {
                return;
            }

            // When a User is logged on, the CurrentUserContextFilter should be enabled.
            if( AppInstance.Current.CurrentUser != null )
            {
                session.EnableFilter (AppInstance.CurrentUserContextFilter)
                                            .SetParameter (AppInstance.CurrentUserContextFilterParameter,
                                                           AppInstance.Current.CurrentUser.Id);

            }
        }
}
于 2011-02-07T15:11:23.390 に答える