应用程序自我感知外部数据库记录修改

时间:2010-04-16 02:58:14

标签: c# sql sql-server

如何让您的应用程序意识到外部应用程序而不是应用程序本身更改或创建了数据库记录?

您是否向数据库记录添加了特殊的校验和,或者您如何停止对数据库的外部更改? (如果它被黑客攻击并且黑客决定添加新记录或更改现有数据库记录)

9 个答案:

答案 0 :(得分:2)

有三个问题被问到:

  

如何确定行已更改?

您有一些选择:

  1. 重新查询数据并进行比较。这将告诉您哪些列已更改(但不一定是由谁更改)。
  2. 使用rowversion列(在旧版本的SQL Server中称为timestamp),每次更改行时都会自行更新。这只会告诉您某些内容已更改,但不会更改哪些列或更改了哪些列。
  3.   

    如何确定该行是由外部应用程序创建的   而不是你自己的应用程序

    这个有点棘手。从技术上讲,您可能认为只需将应用程序的名称写入行中的列可能就足够了,但该技术并不安全。有权保存到此列的外部应用程序可以轻松地执行相同操作。更安全的方法是使用外部监视程序来跟踪对数据库和创建它的用户所做的每个更改。在SQL Server 2008中,有一个名为“更改跟踪”的功能,它围绕类似的功能,也可能就足够了。

      

    如何阻止外部更改   数据库?

    显而易见的选择是限制对数据库的访问。只允许应用程序帐户访问数据库和/或访问表和存储过程。此外,您需要锁定管理员和开发人员对数据库的访问权限,以便只有少数人可以访问数据库。结合良好的日志记录,可以防止出现神秘行。

答案 1 :(得分:0)

通过ORM 一些/所有ORM将生成SQL以匹配对象具有的每个值,并在所有这些条件匹配的情况下运行更新。在这种情况下,重要的是某些字段与“变更指标”保持一致。

--Customer--
ID        int
FirstName varchar(10)
LastName  varchar(10)
ChangedOn datetime

UPDATE Customer
SET FirstName = 'SomeChange'
WHERE FirstName = 'Oldvalue'
andLastName = 'OldValue'
and ChangedOn = SomeDate

家庭烘焙 除了ORM之外,请考虑为您的表实现更新存储过程,该更新存储过程将包括对ChangedOn字段的更新,并在更新记录时使用新的时间戳。这将允许您自己管理更新。在类中为此时间戳定义属性,并在从其数据存储区读取时将其填充到对象中。保存回数据存储区时,请从时间戳的值与当前存储在数据库中的值进行检查。

答案 2 :(得分:0)

您可以做的是创建一个LastUpdated字段,该字段可以使用触发器进行更新。

然后,应用程序可以利用此字段来检查数据是否已过时。

这是一个小例子

CREATE TABLE Vals( 
        ID INT, 
        Val VARCHAR(10), 
        DateCreated DATETIME DEFAULT GetDate(), 
        DateUpdated DATETIME DEFAULT GetDate() 
) 
GO 

CREATE TRIGGER Upd ON Vals 
AFTER UPDATE 
AS  
UPDATE Vals 
SET     DateUpdated = GetDate() 
FROM    Vals INNER JOIN 
        inserted ON Vals.ID = inserted.ID 
Go 

INSERT INTO Vals (ID, Val) SELECT 1, 'A' 
SELECT * 
FROM    Vals 
GO 

UPDATE Vals SET Val = 'B' 
SELECT * 
FROM    Vals 
GO 

DROP TABLE Vals 
GO 

答案 3 :(得分:0)

大多数应用程序使用latest write wins策略。虽然对建筑师没有吸引力,但这很容易编码,而且几乎总是足够好。

如果你真的需要并发的1%的应用程序:

  • 添加UpdateDtUpdatedBy列。如果您在阅读记录后UpdateDt已更改,请发出警告
  • 存储您阅读的行的值,并使用副本存储任何修改。在写入数据库之前,请检查原始值是否仍然匹配。如果他们不这样做,请发出警告。 (这是.NET DataSet使用的策略。)
  • 添加锁定表。当用户打开记​​录时,为其设置锁定。当另一个用户尝试打开行进行修改时,会发出错误消息。与其他方法相反,这称为pessimistic locking,因为它甚至在潜在冲突出现之前就会发出警告。

答案 4 :(得分:0)

这可以在SQL Server中完成,而无需在整个代码中使用触发器,sprocs或强制执行时间戳 - 请参阅rowversion列类型。

答案 5 :(得分:0)

正常的“企业”方法是使用消息队列,通过使用由触发器发布的消息队列,只要有人写入特定的表,您的应用就可以获取消息。它还有一个很大的优势,即您的应用程序不需要运行,但如果您愿意,可以在开始时或按计划读取队列。

请参阅message queue task

答案 6 :(得分:0)

当任何应用程序/用户有权访问表(或表上的可更新视图)时,触发器是捕获所有更改并采取适当操作的唯一可靠方法。

因为触发器不是业务规则或一般数据库完整性的优秀应用程序设计工具,所以在大多数以数据库为中心的应用程序中,数据库确实有自己的职责并且有自己的边界和服务定义,您可以在层中处理它 - 一个人可以访问表,你有不可更新的视图,大多数访问都需要通过存储过程。

即使在数据库具有开放边界的应用程序中,业务规则也会在应用程序的数据层中实施,并且所有访问都应该通过该规则。不幸的是,在这些情况下,开放式外围数据库实际上无法保证更高级别的完整性或对数据的期望,除非帐户确实被锁定,并且只能通过代码中的数据访问层进行访问。

如果您必须让人们直接更新表格,并且您需要在这些特殊情况下强制执行相同的规则,那么触发器实际上是您唯一的选择。至少,您可以使用相对简单的审计触发器来审计所有更改。

答案 7 :(得分:0)

检测客户端离线时发生的更改

这是Change TrackingChange Data Capture的工作。它们都是从Replication派生的技术(一个来自Merge,一个来自Transactional),并由Sync Framework使用。使用CT和/或CDC,应用程序可以连接到数据库并询问“自上次连接以来发生了哪些数据更改?”。这些场景解决了偶尔连接的系统,如笔记本电脑,移动设备等。

在客户端上线时检测更改

这是Query Notifications的工作。该技术基于类似于在线索引的维护方式,并且能够在数据发生变化时主动通知客户端。 QN解决的主要方案是缓存失效。

申请技巧

其他技术是应用程序特定的,如触发器,rowversions,时间戳,ORM中的代码挂钩等等。它们都不是非常可靠,因为引擎不理解它们作为更改跟踪和允许某些不允许的操作(想想在启用复制时禁止的所有操作,如spiting和合并分区)。有些甚至比这种极端情况更糟糕,典型的例子是rowversion和timestamp列,它们在检测删除的行时无可救药。

答案 8 :(得分:0)

到目前为止给出的答案虽然明智,但可能会回答与预期不同的问题。

认为他说:假设有一个难以保护的数据库。如何在发生黑客时检测 理想情况下覆盖好的数据?

如果那是什么意思,那怎么样:

  1. 在每行中保留一个哈希列。它应该从行中的列加上一个私有的'salt'。
  2. 当您的应用程序更改数据时,请让它更新哈希值。一个不知道“盐”的局外人不能这样做。
  3. 在表上放置UPDATE触发器以检查哈希值。如果没有检查,则出现问题,您可以在提交错误数据之前回滚UPDATE
  4. 这很难防止,但它阻止了偶然的破坏。