实施行级安全性(SP 与 LINQ to Objects)
我认为这更多的是关于最佳实践和设计的问题。我尝试搜索与此相关的类似查询,但找不到任何查询。我实际上找到了 实体框架的行级安全性,但我相信这里的上下文有点不同。
我将首先尝试解释我的场景:
我有一个 .net 3.5 网站,它使用通用业务库通过 NHibernate 访问我的 SQL 2008 数据库。所有代码都是 C#,使用 NHibernate 2.1。 我的网站显示来自业务库的不同 IList 负载,业务层通过 NHibernate 从 SQL 获取所有数据。因此,对于 ie,我可以有一个返回 IList 的方法,另一个返回 IList 的方法,另一个返回 IList 的方法,等等...... 关键是,活动用户只能访问所有返回的一部分(几乎所有类型的结果集都必须从安全性角度进行过滤),因此我需要在库上实现一个“数据过滤器”,仅返回允许的数据行到网站。为了实现这一点,库中使用了我网站上的 IPrincipal,这样我就可以获得用户详细信息来过滤数据,但由于我们的安全模型非常复杂,将其分散到我们所有的方法中会产生巨大的维护问题。 因此,为了解决这个问题,我们创建了几个 SQL SP,它们返回当前用户允许的项目,在业务逻辑上,我们只需将请求的数据与安全数据连接起来,就可以将最终结果集发送给用户。 现在,这个连接数据的过程正在使用 Linq to Objects,其中我使用列表(安全性)连接 iList 以仅返回允许的结果集。 IList 通过不同的方式来自 NHibernate,可以通过 GetAll() 方法、ICriteria.List() 或 IQuery.List() 甚至 NamedQuery.List(),并且安全数据始终来自以下之一两个NamedQuery.List()。我还计划实现线程,以允许同时进行 SQL 调用,并在 thread.join() 之后在两个 IList 上执行 LINQ 连接。 我添加了下面的示例代码来说明需要如何执行方法。
第二个选项,也是我们试图摆脱的,是在 SQL 端实现 Join,让我们所有的调用都必须来自 SQL SP,这些 SP 将对安全结果进行联接,并且不允许业务代码获取完整使用NHibernate的功能。
public IList<Product> GetAllByName(string FirstLetter) {
ICriteria GetAllCriteria = this.session.GetISession().CreateCriteria(typeof(Product));
GetAllCriteria.Add(NHibernate.Criterion.Restrictions.Like("ProductName", FirstLetter));
GetAllCriteria.AddOrder(NHibernate.Criterion.Order.Asc("ProductName"));
// Here would go the Threading for the both calls
IList<Guid> AllowedItems = SecurityBase.GetAllowedItemsForCurrentUser();
IList<Product> AllProducts = GetAllCriteria.List<Product>();
var ResultSet = from Prod in AllProducts
join Sec in AllowedItems on Prod.Id equals Sec
select Prod;
return ResultSet.ToList<Product>();
}
现在我的问题是,这对于行级安全性来说是一种糟糕的方法/实践吗(请记住,我们的安全模型非常复杂且可定制——这是由业务设计决定的),还是我们正在朝着正确的方向前进?我们还有其他选择吗?
提前致谢, 克莱顿
I believe this is more a question about best practices and design than anything else. I tried searching for similar queries regarding this but couldn’t find any. I actually found the Row Level Security with Entity Framework but I believe the context here is a bit different.
I will try to explain my scenario first:
I have a .net 3.5 WebSite that uses a common Business Library to access my SQL 2008 Databases via NHibernate. All code is C#, with NHibernate 2.1.
My WebSite displays loads of different ILists coming from the Business Library, the business layer gets all data from SQL via NHibernate. So, for i.e. I could have a method that returns IList another that returns IList, another IList, etc…
The point is that the active user would have access only to part of all the returns (almost all types of resultsets must be filtered from security), so I needed to implement a “data filter” on the library that would return only the allowed data rows to the WebSite. To accomplish this the IPrincipal from my website is used on the Library so I can get the User details to filter the data, but as our security model is highly complex spreading it over all our methods would create huge maintenance problems.
So to solve this we have created a couple SQL SPs that return the allowed items for the current User and on the Business logic we just need to Join the requested data with the security data and we have the final resultset to send to the user.
Right now this process of joining the data is using Linq to Objects where I Join an iList with a List (security) to only return the allowed resultset.
The IList its coming from NHibernate by different ways, could be by a GetAll() method, an ICriteria.List() or IQuery.List() or even a NamedQuery.List(), and the Security data is always coming from one of two NamedQuery.List(). I am also planning to also implement threading to allow both SQL calls simultaneous and after thread.join() execute the LINQ join on both ILists.
I added a sample code bellow to illustrate how a method would need to be executed.
The second option, and this is what we tried to get away off is to implement the Join on the SQL side leaving us with all call must come from SQL SPs that would do the join on the security results and not allowing the business code to get the complete use of NHibernate functionality.
public IList<Product> GetAllByName(string FirstLetter) {
ICriteria GetAllCriteria = this.session.GetISession().CreateCriteria(typeof(Product));
GetAllCriteria.Add(NHibernate.Criterion.Restrictions.Like("ProductName", FirstLetter));
GetAllCriteria.AddOrder(NHibernate.Criterion.Order.Asc("ProductName"));
// Here would go the Threading for the both calls
IList<Guid> AllowedItems = SecurityBase.GetAllowedItemsForCurrentUser();
IList<Product> AllProducts = GetAllCriteria.List<Product>();
var ResultSet = from Prod in AllProducts
join Sec in AllowedItems on Prod.Id equals Sec
select Prod;
return ResultSet.ToList<Product>();
}
Now My question, Is this a terrible approach/practice for Row-Level Security (please keep in mind that our security model is really complex and customizable – and that is by business design) , or are we moving on the right direction? Any other options we could go for?
Thanks in advance,
Claiton
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我目前正在从事一个具有类似要求的项目。这是一个全新项目,尚未编写任何代码,我们只是在寻找基于行的安全性的解决方案。
我会向您推荐这两篇文章:
http://www.codeproject.com/KB/数据库/Modeling_DAGs_on_SQL_DBs.aspx
http://www.codeproject.com/KB/database/AFCAS.aspx
关于您的线程想法,使用 System.Threading 会让您感到悲伤,看看 Ritcher 的 AsyncEnumerator 或 Microsoft Concurrency Runtime (CCR)
I am currently working on a project with similar requirements. It is a green field project, no code has been written yet, we are just looking for a solution to row based security.
I would recommend you these two articles:
http://www.codeproject.com/KB/database/Modeling_DAGs_on_SQL_DBs.aspx
http://www.codeproject.com/KB/database/AFCAS.aspx
With regards to your threading idea, using System.Threading will give you grief, have a look at Ritcher's AsyncEnumerator or Microsoft Concurrency runtime (CCR)
我知道这有点晚了,但您是否看过以下内容:
http://securedata.codeplex.com
这是一个开源项目,我是该项目的首席开发人员,它无缝地实现了行级安全性。
I know this is a little late but have you taken a look at the following:
http://securedata.codeplex.com
This is an open source project I am the lead developer for and implements row level security seamlessly.
作为一种选择,您是否考虑过不使用 SQL SP 返回允许的项目列表,而是在视图内部使用相同的逻辑/联接,并且仅查询视图/仅向视图而不是基础表提供权限。
As an option, have you considered that instead of using the SQL SP to return the list of allowable items you use the same logic / join inside of a view and only queried the views / only provided permission to the view and not the underlying table.