背景 我一直在使用C#在ASP.NET 4.0中开发一个小概念验证Web应用程序,我一直在使用Linq To SQL,因为它快速而简单。我现在必须限制一个用户在同一个数据库中查看另一个用户的数据。所以我在我的大多数表格中添加了一个“帐户”列,我想在允许他们访问之前检查当前用户是否是他们正在查看/编辑的数据的同一帐户的成员。
我不满意的一个可能的解决方案: 我可以简单但痛苦地浏览我的所有Linq To SQL查询并添加一个if语句来执行这样的检查:
MyDataContext DB = new MyDataContext();
//get the current user's information from the DB
USER myUser = DB.USERs.Where(j => j.USR_EMAIL == User.Identity.Name).FirstOrDefault();
//get the object to edit
MYOBJECT myObject= DB.MYOBJECTs.Where(j => j.ID == IdFromQueryString).FirstOrDefault();
//compare the user's account with the object's account they are now trying to view
if(myUser.AccountID == myObject.AccountID)
{
//display the object
}
else
{
//display error message
}
在整个应用程序中要做很多工作,更不用说错误的重复和机会了。维护也很痛苦,如果我忘记添加这个查询,我会打开一个安全漏洞。
问题: 有没有办法为每个表执行一次,并且每次使用Linq To SQL进行查询时都会自动检查?或者有更好的方法来解决这个问题吗?
答案 0 :(得分:3)
您应该使用Repository模式而不是直接访问Contest.Users
,但始终可以访问Repository.Users
。然后,您可以更改存储库以将Users
公开为from u in InternalContext.Users where u.AccountId = currentAccountId select u
,从而强制执行范围。巧合的是,这种技术是called a scope in Rails ......
下一个最好的方法是使用DataLoadOptions
将lambda过滤器与您的实体相关联,请参阅How to: Filter at the DataContext Level (LINQ to SQL)。您需要将此添加到您创建的每个上下文中。同样,重构代码以从方法中获取数据上下文(或者更好,实现存储库模式......)将会有很大帮助。
最后你可以在后端通过可更新的视图和context_info()
实现这一点,但我强烈反对这一点。
PS。我希望你在表上的每个聚簇索引中创建account_id
最左边的键,并使实体id
主键非clustred,是吗?否则你的表现将会成为现实。
答案 1 :(得分:1)
对不起,你有两个对象的AccountID吗?如果是这样,你有没有理由不能加入他们的Accountid?
var query = from o in DB.MYOBJECTs.Where(w => w.ID == IdFromQueryString)
join u in DB.USERs.Where(w => w.USR_EMAIL = User.Identity.Name) on o.AccountID equals u.AccountID
select o;
答案 2 :(得分:0)
两种可能的方法:
这些与您当前包装每个查询的策略根本不太相似,但可能更容易管理。