去年年末最后几天,我曾经在CSDN上提出过这么个问题
如何防止mdf文件被非法附加?虽然没有得到很好的解决方案,但是还要感谢诸位网友的热心建议。
再次阐述以下一下问题:
我们做的系统面临这么个问题,数据库在发布的时候是在安装时指定的实例上加了特定的密码。用SQL Server2000客户端直接连这个实例是无法正常连接的,但是有些稍微懂点SQL Server技术的客户能建个实例并把mdf文件附加到新建实例就可以堂而皇之的修改了,绕过程序的控制了,请问有没有什么好的办法可以防止这种情况的发 生?
前些天在找资料的时候无意中发现Sql Server 2000提供了一个全局变量——@@DBTS,联想到前段时间一直困扰我的关于如何防止用户非法修改数据库的问题,觉得通过这个变量来控制比较方便。
当然也是一种消极的事后控制方法,但也最起码也是一种方法,于是随手做了个简单的demo,确实很简单,下面是主要步骤及伪代码实现:
0.认识 @@DBTS(来自msdn)
为当前数据库返回当前 timestamp 数据类型的值。这一 timestamp 值保证在数据库中是唯一的。
语法
@@DBTS
返回类型
varbinary
注释
@@DBTS 返回当前数据库最后所使用的时间戳值。当带有 timestamp 列的一行被插入或更新时,会产生 一个新的时间戳值。
示例
下面的示例从 pubs 数据库返回当前的 timestamp 值。
USE pubs
SELECT @@DBTS
1.建立两个实验表:
//加密存储系统当前的@@DBTS变量
CREATE TABLE [dbo].[dbts_log] (
[dbtslog] [char] (18) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [PRIMARY]
GO
//实验数据表,必须有timestamp字段
CREATE TABLE [dbo].[dbts_test] (
[TestID] [uniqueidentifier] NOT NULL ,
[name] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
[timestamp] [timestamp] NULL
) ON [PRIMARY]
2.建立两个全局函数:
//a.f_updatedbts 在更改业务数据时同时更新DBTS_Log记录
String Ls_DBStamp
String Ls_DBTSLog
//取出数据库@@DBTS
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA ;
PREPARE SQLSA FROM "SELECT @@DBTS" ;
OPEN DYNAMIC my_cursor ;
FETCH my_cursor INTO :ls_DBStamp ;
CLOSE my_cursor ;
//更新前先验证DBTS_LOG表记录值是否与@@DBTS相符
SELECT dbtslog
INTO :ls_DBTSLog
FROM dbts_log;
//TODO 采取加密存储,这里进行解密
IF ls_DBStamp = ls_DBTSLog Then
//更新记录表,一定要考虑加密存储,而且是不可逆的加密算法
UPDATE dbts_log
SET dbtslog = :ls_DBStamp;
IF Sqlca.SqlCode <> 0 Then
Rollback Using Sqlca;
Return False
Else
IF pb_iscommit Then
Commit Using Sqlca;
End IF
End IF
Else
Return False
End IF
Return True
//b.f_validdbts 验证DBTS_log记录是否非法
String ls_DBStamp
String ls_DBTSLog
//取出数据库@@DBTS
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA ;
PREPARE SQLSA FROM "SELECT @@DBTS" ;
OPEN DYNAMIC my_cursor ;
FETCH my_cursor INTO :ls_DBStamp ;
CLOSE my_cursor ;
//取出表中记录的DBTS日志
SELECT dbtslog
INTO :ls_DBTSLog
FROM dbts_log;
//TODO 采取加密存储,这里进行解密
//返回比较的结果
Return (ls_DBStamp = ls_DBTSLog)
3.简单实验:
a )//通过程序修改带有timestamp字段的表
INSERT INTO dbts_test
( name )
VALUES ( "new" ) ;
//同时更新DBTS_LOG表
f_updatedbts(true)
b)在打开系统时校验DBTS_LOG表记录值是否与@@DBTS相符
IF Not f_validdbts() Then
MessageBox("**系统",“程序检测到您当前数据库被非法修改,请与系统管理员联系!”)
Halt
End IF
ps:我伪代码是用比较古老的语言powerbuilder,比较浅显易懂,所以也没特意修改