如何限制用户仅使用Linq To SQL编辑其数据?

时间:2012-07-10 04:54:53

标签: c# asp.net .net linq-to-sql

背景 我一直在使用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进行查询时都会自动检查?或者有更好的方法来解决这个问题吗?

3 个答案:

答案 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)

两种可能的方法:

  • 使用存储过程访问数据而不是直接查询;仅授予用户对这些存储过程的权限(即,不对数据库进行一般读取访问),并使存储过程强制执行访问限制。
  • 通过单独的服务代理对数据库的所有访问 - 该服务是唯一具有对数据库的一般访问权限并且可以强制执行访问限制的服务。

这些与您当前包装每个查询的策略根本不太相似,但可能更容易管理。