NHibernate 预选?

发布于 2024-10-16 03:48:37 字数 410 浏览 1 评论 0原文

我正在尝试使用 NHibernate 实现权限,而我想要做的是,每次有一个 Select 查询时,检查返回类型是什么,如果它是启用安全的类型(例如发票),我想添加限制到 ICriteria 对象,以限制仅检索某些记录(根据用户是否已读取全部或读取自己的权限)。

我设法使用插入和更新实现这些权限,

NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener

但不幸的是,在查询数据库后调用 IPreLoadEventListener ,因此这是浪费,因为过滤将在计算机上本地完成,而不是通过数据库。

有谁知道 NHibernate 是否提供了某种在执行查询之前调用的事件?

I am trying to implement privileges using NHibernate, and what I want to do, is each time there is a Select query, check what the return type is, and if it is a security enabled type (such as invoices) i want to add restrictions to the ICriteria object, to restrict retrieving only certain records (According if the user has read all, or read own privileges).

I managed to implement these kind of privileges for Insert and Update using

NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener

but unfortunately the IPreLoadEventListener is called after the database is queried, and therefore it is waste as the filtering will be done locally on the computer rather then by the database.

Does anyone know if NHibernate provides some sort of event that is called before a query is executed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把梦留给海 2024-10-23 03:48:37

如果您能够使用它,请查看 Rhino.Security 它的功能完全符合您的要求正在努力做。即使你无法使用它,你也可以看到他对这个问题的实现。

If you're able to use it, check out Rhino.Security It does exactly what you're trying to do. Even if you're unable to use it, you can then see his implementation of this problem.

愁以何悠 2024-10-23 03:48:37

你不能通过使用 Filter 来实现这一点吗?

更多信息可以在此处找到,

我已经使用过这个与我的项目中的拦截器结合使用:

我有一些实体,每个用户都可以从中创建实例,但只有创建它们的用户应该能够查看/修改这些实例。其他用户无法看到用户 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);

            }
        }
}

Can't you achieve this by using Filters ?

More information can be found here

I've used this in combination with Interceptors in a project of mine:

I have some entities where each user can create instances from, but only the user who has created them, should be able to see / modify those instances. Other users cannot see instances created by user X.

In order to that, I've created an interface IUserContextAware. Entities that are 'user context aware' implement this interface.

When building my session-factory, I created the necessary filters:

 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));

When this was done, I needed to define the additional filter criteria:

 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;
     }
 }

Now, whenever I instantiate an ISession, I specify that a certain interceptor should be used:

This interceptor makes sure that the parameter in the filter is populated:

    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);

            }
        }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文