|
想当初,偶阿罗刚来这里的时候,也是拿这个问题来探探水温,好像乐于回答的不多,论坛里也查不到明确的解答,害得我只好自问自答。现在,本着为人民服务的精神,将自己的心得体会全部写下,此为本人原创。
首先,应该明白,虽然微软的东西有时候很烂,不过应该相信还不至于烂到这种程度: 出了一个茅,破了自己的盾。
按照微软的设计,安全性本来就应该在域和SQL服务器层面上解决。所以,对于你的问题,泛泛而谈的一个回答就是,将所有的用户权限都在sql服务器上设置好。SQL服务器提供了强大的安全功能,特别是同windows安全新集成的情况下。SQL服务器的系统存储过程还提供用户使用编程来管理安全性,作为一个开发人员,需要熟悉和使用这些资源。另外,从现实层面讲,一个大的公司,数据的管理同数据分析可能是分开的,作为SQL服务器那一部分,它的功能就是要定义数据库对象让某些部门和个人可以使用而另外不能使用。至于怎么使用,那就不是他们的事情。它很可能就担任一个“提供者”的功能。这也就是为什么微软要如此设计的原因。
所以,按照上面的论述,具体的做法就是,对于不应该由任何用户直接看到的表(我想主要就是指表,因为这个是原始数据),需要用存储过程、函数、加密的视图等来向用户提供数据。有的人好像不太喜欢编写存储过程,认为用起来太麻烦。但是,同获得的安全性相比,这是微不足道的。再说,如果熟悉了存储过程,用起来也不麻烦,不但如此,有的事情,不用存储过程还不好办。
总结起来,基本上就是使用存储过程代替对表的原始操作,在表上加限制,对存储过程添加相应权限。
当然,对于简单的C/S应用来讲,大致上还有两种方法可以绕开sql服务器的权限设定。
一,用户实际登陆SQL服务器的账号没有任何察看和修改数据的权限,登陆以后,用程序来进行另外一个连接,而这个连接是用户不知晓的,并被授予相应的权限,更多的限制可能需要归到窗口控件级。但是,这个解决方案,在sql服务器仅使用trusted_connection的时候,是无能为力的,同时也很难区别不同的用户。有一些论述是使用本地工作站用户一个密码文件,而SQL那里还是用传统用户加口令的认证办法,这些都不是解决问题好办法。
第二,使用sql服务器的应用程序角色。这个有一大堆东西可以讨论,细节请自行察看sql帮助文档。应用程序角色,同其他普通角色不同,他们并不包含任何用户,相反,用户还是用他们自己的登陆方式登陆服务器,然后,通过执行sp_setapprole来激活这个特殊角色。在应用程序角色激活以后,用户本身的登陆在整个应用程序连接过程中完全失效,从而保证了用户不能从应用程序以外再次登陆服务器。当然,为了保险,还是应该将用户的数据库使用权限限制到最低,而这种限制可以是完全限制访问,除了sp_setApprole。
在Access ADP 中,基本程序(没有连接判断、错误控制句柄等)可能是这样的(首先在sql服务器中创建这个角色,例如testApp,密码mypass):
Private Sub ActivateAppRole()
Dim TSQL As String
TSQL = "EXEC sp_setapprole 'testApp', {Encrypt N 'mypass'}, 'odbc'"
Application.CurrentProject.Connection.Execute TSQL
End Sub
当然,可以用sp_addapprole, sp_dropapprole来编程创建应用程序角色,也同其他角色类型一样可以对其授权。
值得注意的是,如果使用这个方案,由于adp通常用3个连接同服务器器通讯,其中第一个是程序启动后在内建数据库窗口建立可浏览对象因此无法对其进行setapprole,但是这并不重要,因为你以后不可能让用户显示这个窗口的(更有可能你用ade发行),而第二个连接和第三个连接(第三个连接通常是获取combo, list, reports)就需要按照上述代码处理了。另外,还有一些问题,例如子窗体不能正确联动。这是因为access通常(但并不总是)会创建新的连接来处理子窗体。因此,子窗体也许可以不采用绑定,而用手工编程;如果采用绑定,那么唯一正确处理方法就是在主窗体的current事件里面创建一个新的连接,然后取得子窗体的记录集。在子窗体设计的时候,采用绑定设计,然后将其默认数据源删除。
从网络数据流量方面来讲,用一个导航条在主窗体循环,然后在子窗体显示大量关联记录的方法,是不合适的。因此,一般都应该使用一个查询取得主窗体记录的索引,然后每次查询并显示一条主窗体记录和一个子窗体关联记录集。
设计的时候i,一般使用上述代码在一个启动窗体上添加第二和第三个连接。第三个连接可以使用一个隐藏的listbox作一个空查询。 |
|