Sql 判断一行数据是否已更改的简单方法是什么?

Sql 判断一行数据是否已更改的简单方法是什么?,sql,sql-server,database,security,Sql,Sql Server,Database,Security,如果我有一行数据,如: 1, 2, 3 我可以创建一个校验和值,它是所有列的总和,1+2+3=6。我们可以将该值与第4列中的行一起存储: 1, 2, 3, 6 然后我可以编写一个程序来检查,如果列的总和与校验和值不匹配,列中的任何值是否会意外更改 现在,我想更进一步。假设我有一个任何人都有读/写权限的值表,其中最后一列数据是前面描述的前几列的总和 1, 2, 3, 6 假设有人想偷偷摸摸地改变第三列中的值 1, 2, 9, 6 校验和很容易复制,因此偷偷摸摸的人只需将校验和值更改为1+2

如果我有一行数据,如:

1, 2, 3
我可以创建一个校验和值,它是所有列的总和,1+2+3=6。我们可以将该值与第4列中的行一起存储:

1, 2, 3, 6
然后我可以编写一个程序来检查,如果列的总和与校验和值不匹配,列中的任何值是否会意外更改

现在,我想更进一步。假设我有一个任何人都有读/写权限的值表,其中最后一列数据是前面描述的前几列的总和

1, 2, 3, 6
假设有人想偷偷摸摸地改变第三列中的值

1, 2, 9, 6
校验和很容易复制,因此偷偷摸摸的人只需将校验和值更改为1+2+9=12,这样这一行就不会被篡改

1, 2, 9, 12
现在我的问题是,我怎样才能生成一个更复杂的校验和值,这样一个狡猾的人就不能在不使校验和失效的情况下进行这种类型的更改?也许我可以创建一个blackbox exe,给定行的前三个值,它可以给出一个更复杂的校验和,如:

a^2 + b^2 + c^2
但是,尽管这个逻辑对于一个狡猾的用户来说是未知的,他/她仍然可以将这些值输入到黑盒exe中并得到一个有效的校验和


关于如何确保表中的所有行都不受干扰,有什么想法吗?我试图避免的方法是,每次使用我正在创建的程序对表进行合法修改时,都保存一份表的副本。这是可能的,但似乎是一个非常不公平的解决方案。必须有更好的方法,对吗?

使用基本数学,您的校验和无效:

a^2 +b^2 +c^2  

a=0,b=0,c=2  = checksum 4
a=2,b=0,c=0  = checksum 4

如果你想要一组“只读”数据给用户,考虑使用物化视图。物化视图将计算一个时间头,即您的有效数据,并将其提供给用户,而您的程序可以在后台进行修改

此外,这也是为什么存在特权的原因,如果您只提供无法修改数据库的帐户(例如只读访问),这将减轻有人篡改数据的问题。此外,您无法完全防止恶意用户篡改数据,只能让他们跳过几个障碍,希望他们暂时感到无聊/被阻止

安全方面没有银弹,您可以做的是使用由以下功能组成的纵深防御心态:

大量日志记录,
职责划分,
工作轮换,
修补程序管理,
日志审核(与日志一起进行,但实际上必须有人阅读日志),
实施HIPS系统(主机入侵防御系统),
拒绝与数据库的外部连接

这个列表可能会非常广泛。

您似乎在问,“我如何才能为运行程序的用户授予一组不同的安全权限?”这样做的方法是确保该程序在与用户不同的安全上下文中运行。这样做的方式因平台而异

如果您有多台计算机,那么运行客户机-服务器体系结构会有所帮助。您可以通过服务器公开一个受控API,并且该API具有数据库的安全凭据。这样,您的用户就不能发出任意请求

如果您是客户机的管理员,而用户不是,那么您可以让单独的进程执行类似的操作。例如,unix中的守护进程。我认为windows中的DCOM允许您执行类似的操作

另一种方法是通过存储过程公开API,只授予对这些过程的访问权,而不是直接访问表


对有限的API进行受控访问可能是不够的。例如,考虑一个在游戏中存储高分的表格。如果用户可以输入任意值,则只能通过
ClaimHighScore
API访问它并不重要。在游戏中解决这个问题通常很复杂。我听说过的唯一有效的方法是根据给出初始游戏状态的种子值定义API,然后是一组带有时间戳的输入。然后,服务器必须模拟游戏来验证分数。

用户不应拥有对表的无限制写访问权。最好是为常见的CRUD操作创建存储过程。这将允许您控制他们可以修改哪些字段,如果您坚持,您可以更新
CRC()
校验和或其他验证


这将是一个大项目,所以现在可能不太实际,但这是应该如何做的。

尽管您的问题是基于对数据库的恶意输入,但使用会发现不准确或错误的值

下面是MySQL语句,并对此进行了说明

SELECT id, col1, col2, col3, col4, checknum,
9 - MOD(((col1*5)+(col2*4)+(col3*3)+(col4*2) ),9) 
AS Test FROM  `modtest` HAVING checknum =Test

您使用的是哪种数据库管理系统?基于DBMS,您可以使用内置校验和或CRC函数。如果您不希望人们更新行,则不授予更新权限。@Laurence甚至不远程解决恶意用户的问题。编辑日志/监视是检测DBMS中恶意/恶意更改的安全方法,不是应用程序或数据库校验和。+1@Laurence这可能是我建议的路线。另外,您的用户将如何更新这些值?他们是否可以直接访问数据库(在这种情况下,您所做的任何操作都不会阻止他们进行他们想要的任何更改)?确实如此。当你刚说建议的校验和将无效时,我在第一次发布时看到了它。@SPFiredrake它发生了:)