Mar*_*ann 10 .net security linq-to-entities entity-framework least-privilege
我们使用LINQ to Entities将条目写入Audit数据库(SQL Server 2008).由于这是一个专用的审计数据库,我们只插入行 - 我们从不读取任何行,从审计应用程序更新或删除它们.
审计应用程序应使用最小权限原则,因此我们不希望授予它超出其需要的权限.由于我们从未读过任何行,因此我们不希望授予从数据库中进行选择的权限.
但是,当我们尝试写入数据时,会收到以下错误消息:
对象'AuditEvent',数据库'IdentifyAudit',架构'dbo'上的SELECT权限被拒绝.
代码是非常标准的EF代码:
var auditEvent = new AuditEvent();
auditEvent.EventType = eventType;
auditEvent.Timestamp = timestamp;
auditEvent.UserName = userName;
auditEvent.ApplicationId = this.ApplicationId;
this.objectContext.AddToAuditEvents(auditEvent);
this.objectContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
为什么我们需要SELECT权限才能写入表格,更重要的是:我们有什么办法可以删除这个要求吗?
编辑
SQL事件探查器显示正在执行的语句:
exec sp_executesql N'insert [dbo].[AuditEvent]([EventType], [Timestamp], [UserName], [ApplicationId])
values (@0, @1, @2, @3)
select [Id]
from [dbo].[AuditEvent]
where @@ROWCOUNT > 0 and [Id] = scope_identity()',N'@0 nvarchar(10),@1 datetimeoffset(7),@2 nvarchar(11),@3 nvarchar(36)',@0=N'UpdateUser',@1='2009-11-10 10:58:33.2814740 +01:00',@2=N'foo',@3=N'bar'
Run Code Online (Sandbox Code Playgroud)
这解释了为什么需要SELECT权限,因为该操作返回插入行的自动生成的ID.
问题现在仍然存在:我不需要知道我刚刚插入的行的ID,所以有什么方法可以关闭此功能吗?
默认情况下,在向ObjectContext添加实体并调用SaveChanges后,该对象的状态将从Added更改为Unchanged,并且仍由ObjectContext跟踪.这就是EF需要该ID以便能够跟踪其变化的原因.
1.构造实体对象.此时,键属性都具有默认值,null或0.
2.通过在上下文中调用AddObject或其中一个特定于实体集的add方法,或者通过在返回EntityCollection的导航属性上调用Add,将新对象添加到ObjectContext.
此时,对象服务生成一个临时密钥,用于在ObjectStateManager中存储对象.
3.SaveChanges在ObjectContext上调用.
INSERT语句由实体服务生成,并在数据源上执行.
4.如果INSERT操作成功,则将服务器生成的值写回ObjectStateEntry.
5. ObjectStateEntry使用服务器生成的值更新对象.
6.当在ObjectStateEntry上调用AcceptChanges时,将使用新的服务器生成的值计算永久的EntityKey.
所以,据我所知,不可能从ObjectContext切换这个功能,我没有看到这个问题的任何"好"的解决方案:你可以避免这种情况的一种方法是使用自己的存储过程来插入实体(如果可以)(http://msdn.microsoft.com/en-us/library/bb399203.aspx).
此外,如果没有服务器生成的ID,我认为不会执行选择查询(再次,如果你可以改变dbs,如果你想打扰生成id).