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

C# 如何限制用户仅使用Linq to SQL编辑其数据?,c#,asp.net,.net,linq-to-sql,C#,Asp.net,.net,Linq To Sql,背景: 我一直在用C在ASP.NET4.0中开发一个小型概念验证web应用程序,我一直在使用LINQtoSQL,因为它既快速又简单。我现在必须限制一个用户在同一数据库中查看另一个用户的数据。因此,我在我的大多数表中添加了一个“account”列,在允许当前用户访问之前,我想检查当前用户是否与他们正在查看/编辑的数据属于同一个帐户 我不太满意的一个可能的解决方案是: 我可以简单但痛苦地完成所有Linq到SQL查询,并添加一个if语句来执行如下检查: MyDataContext DB = new M

背景: 我一直在用C在ASP.NET4.0中开发一个小型概念验证web应用程序,我一直在使用LINQtoSQL,因为它既快速又简单。我现在必须限制一个用户在同一数据库中查看另一个用户的数据。因此,我在我的大多数表中添加了一个“account”列,在允许当前用户访问之前,我想检查当前用户是否与他们正在查看/编辑的数据属于同一个帐户

我不太满意的一个可能的解决方案是: 我可以简单但痛苦地完成所有Linq到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进行查询时自动进行检查?或者有更好的方法吗?

两种可能的方法:

使用存储过程访问数据,而不是直接查询;仅向用户授予对这些存储过程的权限,即不对数据库进行常规读取访问,并让存储过程强制执行访问限制。 通过一个单独的服务代理对数据库的所有访问—该服务是唯一对数据库具有常规访问权限的服务,并且可以强制执行访问限制。
这些与您当前包装每个查询的策略没有太大区别,但可能更易于管理。

两种可能的方法:

使用存储过程访问数据,而不是直接查询;仅向用户授予对这些存储过程的权限,即不对数据库进行常规读取访问,并让存储过程强制执行访问限制。 通过一个单独的服务代理对数据库的所有访问—该服务是唯一对数据库具有常规访问权限的服务,并且可以强制执行访问限制。
这些与您当前包装每个查询的策略基本上没有太大区别,但可能更易于管理。

对不起,您是否为这两个对象都提供了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;

对不起,两个对象都有可用的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;
您应该使用该模式,而不是直接访问Contest.Users,而是始终访问Repository.Users。然后您可以将存储库更改为在InternalContext中从u公开用户。u.AccountId=currentAccountId的用户选择u,从而强制作用域。巧合的是,这种技术

下一个最好的方法是使用lambda过滤器与实体关联,请参见。您需要将其添加到您创建的每个上下文中。同样,重构代码以从方法或更好的方法获得数据上下文,实现存储库模式。。。会有很大帮助的

最后,您可以在后端通过可更新的视图实现这一点,但我强烈反对这样做

另外,我希望您将account_id设置为表上每个聚集索引中最左边的键,并将entity id主键设置为非聚集键,是吗?否则您的性能会下降。

您应该使用该模式,而不是直接访问Contest.Users,而是始终访问Repository.Users。然后您可以将存储库更改为在InternalContext中从u公开用户。u.AccountId=currentAccountId的用户选择u,从而强制作用域。巧合的是,这种技术

下一个最好的方法是使用lambda过滤器与实体关联,请参见。您需要将其添加到您创建的每个上下文中。同样,重构代码以从方法或更好的方法获得数据上下文,实现存储库模式。。。会有很大帮助的

最后,您可以在后端通过可更新的视图实现这一点,但我强烈反对这样做


另外,我希望您将account_id设置为表上每个聚集索引中最左边的键,并将entity id主键设置为非聚集键,是吗?否则您的性能会下降。

不要忘记sql函数。。。与存储过程不同,这些可以组合在任意且相对高效的sql查询中。不过,我不知道这对linq到sql的转换有多好。我真的不知道单独的服务是什么意思,你能给我一个例子吗?有一个单独的进程,它是唯一可以访问数据库并通过某种形式的RPC与该进程对话的东西。这使您能够很好地区分关注点,这有一些优点:例如,即使您的主程序存在安全缺陷,您也不会影响对数据库的访问。当然,服务中的缺陷是另一个问题
课程不过,我怀疑这对于您的用例来说可能太重了。好吧,是的,对于我的特定应用程序来说,这有点过火了,但是对于其他项目,需要记住一些事情。谢谢不要忘记sql函数。。。与存储过程不同,这些可以组合在任意且相对高效的sql查询中。不过,我不知道这对linq到sql的转换有多好。我真的不知道单独的服务是什么意思,你能给我一个例子吗?有一个单独的进程,它是唯一可以访问数据库并通过某种形式的RPC与该进程对话的东西。这使您能够很好地区分关注点,这有一些优点:例如,即使您的主程序存在安全缺陷,您也不会影响对数据库的访问。当然,服务中的缺陷是另一个问题。不过,我怀疑这对于您的用例来说可能太重了。好吧,是的,对于我的特定应用程序来说,这有点过火了,但是对于其他项目,需要记住一些事情。谢谢我刚刚意识到我将给出的答案与您答案的第一部分基本相同,但我要强调的是,如何让存储库返回IQueryables,以便在数据库级别高效地进行进一步的筛选。Repository模式是与IQueryables一起使用的非常好的模式;谢谢你提醒我,你是冠军。不,我没有像你描述的那样编制索引,但我现在会。存储库模式听起来不错-你能推荐一些可以帮助我开始使用它的资源吗?举个例子就好了?另外,感谢JayC提到IQueryables——我还没听说过这些before@Dean:一切都很好LINQ基本上是个易货。至于存储库模式,这个主题更为复杂,它与TDD测试驱动开发和IoC控制反转等概念结合在一起。首先。关于Channel9有一个很好的教程,但我就是找不到。我刚刚意识到我要给出的答案基本上与您答案的第一部分相同,但我要强调的是,如何让您的存储库返回IQueryables,以便在数据库级别有效地进行进一步的过滤。Repository模式是与IQueryables一起使用的非常好的模式;谢谢你提醒我,你是冠军。不,我没有像你描述的那样编制索引,但我现在会。存储库模式听起来不错-你能推荐一些可以帮助我开始使用它的资源吗?举个例子就好了?另外,感谢JayC提到IQueryables——我还没听说过这些before@Dean:一切都很好LINQ基本上是个易货。至于存储库模式,这个主题更为复杂,它与TDD测试驱动开发和IoC控制反转等概念结合在一起。首先。关于Channel9有一个很好的教程,但我就是找不到。是的,我有两个对象的AccountId。谢谢你更简洁的代码,它肯定比我的好!然而,我的理想解决方案是,我可以在一个地方管理这段代码。是的,我有两个对象的AccountId可用。谢谢你更简洁的代码,它肯定比我的好!然而,我的理想解决方案是在一个地方管理代码