我们使用NHibernate,因此我们构建了一个提供实体的类。它看起来像这样:
class DataProvider {
TEntity Get<TEntity>(int id) {
return GetSession().Get<TEntity>(id);
}
IQueryable<TEntity> Query<TEntity>()
{
return GetSession().Query<TEntity>();
}
// ...
}
这使我能够调用
DataProvider.Get<Person>(1)
或使用from person in DataProvider.Query<Person>() select person
进行LINQ查询。使用拦截器将允许我拒绝用户未获得授权的任何单个对象(尽管可以争辩这段代码可以插入到DataProvider.Get
中)。当我尝试使用LINQ时,这变得麻烦。假设我有一个包含100万个实体的表,但我只能访问其中的5个实体。使用拦截器会检索整个表,并测试返回的每个实体,但我只需要其中的5个。我想到的最好的方法是注入一些自定义SQL以告诉NHibernate应该检索哪些对象并忽略所有其他对象。我们已经有了一个系统来确定我们是否有权访问对象,让我们假设我们也知道如何从中制作一个查询。
我尝试了什么?
- 拦截器(太晚了,即使只需要5个对象,也会检索1百万个对象)。
- 事件(IPostLoadEvent最接近我所需的内容,但它太晚了)。
- 自定义NhQueryable和DefaultQueryProvider。这会抛出异常:“
The constant for 'MyQueryable<Person>' is not supported
”,我认为这是由于NHibernate深处的某个地方进行了强制转换。我怀疑NHibernate没有设计成允许自定义查询提供程序或可查询。 - OnPrepareStatement拦截器。这非常丑陋。它允许我编辑SQL,但我得到的只是一个字符串。这能够工作,但我希望有一种更优雅的方法来做同样的事情。
其他人如何处理授权代码?您如何确保没有人忘记调用授权检查?