【问题标题】:User level security?用户级安全?
【发布时间】:2013-11-05 19:32:51
【问题描述】:

我有一个表,其中包含用户名、密码和 isadmin 的是/否列。

如果他们使用在“isadmin”下有复选标记的帐户登录,我该如何做到这一点,他们可以访问设计视图、功能区等?虽然如果他们使用在 isadmin 框下没有复选标记的帐户登录,他们只能查看表单,不能编辑它们,并且功能区无法访问?

我只是不知道从哪里开始,因为我假设有一种方法可以将数据库保存为只有用户才能查看表单的单独副本,如果管理员运行他的副本,他会获得所有更改用户制作的表格(通过表格)。因此,当管理员编辑表单并保存它时,它不会像保存时那样删除所有用户的数据,它也被保存到管理员的副本中。我真的很困惑。

我正在使用 Access 2013

【问题讨论】:

  • 我可以以某种方式将我的数据库转换为旧的吗?
  • 好的,现在它是旧版本;如何设置用户级安全性?
  • 请注意,用户级安全性也已弃用。如果您构建依赖于它的新应用程序,您还必须接受未来更新可能会破坏它的风险,如果发生这种情况,它将无法得到修复。
  • 我决定使用表格、查询、vba 和按钮制作自己的 USL。完成后我会在这里报告。如果我完全完成它,它将在 2013 年工作。

标签: sql vba ms-access code-access-security


【解决方案1】:

这是在较新版本的 Access 中删除用户级安全性的简单解决方案;使用大量的 VBA。

第 1 步:创建表格

首先,创建一个表。我会命名我的LogininfoT。现在,对于表内的列,将它们命名为 EmployeeIDLoginIDLoginPasswordEmployeeName,最后是 IsAdmin。将 EmployeeID 设为您的密钥,并将 IsAdmin 设为 YES/NO 字段。

为了测试,将两个用户添加到此表中。有了这些信息:

EmployeeID LoginID LoginPassword EmployeeName IsAdmin
1          1111    1234          Bob          [x]
2          2222    1234          Stewert      [ ]

第 2 步:创建表单

现在我们已经制作好了表格,让我们设计表格来使用这组数据。

我将我的表单命名为 LoginF。进入设计视图,按下一个文本框、一个组合框和一个按钮。对于组合框,将文本重命名为“登录 ID”(您可以将其更改为适合您需要的任何内容),对于文本框,将文本输入为密码(再一次,将其更改为您想要的任何内容,它不会影响结果)。按钮中的文字可以是任何你想要的,我会在上面放上登录。

单击组合框并将其重命名。我将把它命名为 LoginCmBx。接下来,单击文本框并将其重命名,我将其命名为 PasswordTxt。最后,点击按钮并重命名,我将其命名为 LoginBtn。

再次单击组合框并在事件选项卡下,进入更新后脚本。使用代码并输入:

Private Sub LoginCmBx_AfterUpdate()

    Me.PasswordTxt.SetFocus

End Sub

这使得在您选择用户名后,它会自动将焦点放在密码文本框上,这样您就可以立即开始输入,而无需使用键盘上的 TAB 或鼠标。

接下来,转到按钮并在事件选项卡下,进入 On Click 脚本。使用代码并输入:

Private Sub LoginBtn_Click()

    If IsNull(Me.LoginCmBx) Or Me.LoginCmBx = "" Then
      MsgBox "You must enter a User Name.", vbOKOnly, "Required Data"
        Me.LoginCmBx.SetFocus
        Exit Sub
    End If

    If IsNull(Me.PasswordTxt) Or Me.PasswordTxt = "" Then
      MsgBox "You must enter a Password.", vbOKOnly, "Required Data"
        Me.PasswordTxt.SetFocus
        Exit Sub
    End If

    If Me.PasswordTxt.Value = DLookup("LoginPassword", "LoginInfoT", _
            "[EmployeeID]=" & Me.LoginCmBx.Value) Then

        EmployeeID = Me.LoginCmBx.Value

           On Error Resume Next
           DoCmd.DeleteObject acQuery, "IsAdminQ"
   On Error GoTo Err_LoginBtn_Click

   Dim qdef As DAO.QueryDef
   Set qdef = CurrentDb.CreateQueryDef("IsAdminQ", _
                                       "SELECT IsAdmin " & _
                                       "FROM LoginInfoT " & _
                                       "WHERE EmployeeID = " & LoginCmBx.Value)

Exit_LoginBtn_Click:
DoCmd.Close acForm, "LoginF", acSaveNo
        DoCmd.OpenForm "MenuF"
   Exit Sub
Err_LoginBtn_Click:
   MsgBox Err.Description
   Resume Exit_LoginBtn_Click

    Else
      MsgBox "Password Invalid. Please Try Again", vbOKOnly, _
            "Invalid Entry!"
        Me.PasswordTxt.SetFocus
    End If

End Sub

它的作用是检查您是否选择了一个用户名,如果没有,它会吐出一个错误,告诉用户选择一个。如果你这样做了,它会检查你是否输入了密码。如果他们没有,它会吐出另一个错误,说他们没有输入密码。如果他们同时选择了这两个,并且密码与表中您选择的用户名的密码不匹配,则会吐出一个错误,提示您密码错误。如果您获得了所选用户名的正确密码,它会登录。然后它将关闭您当前所在的表单,并打开一个名为“MenuF”的新表单,它还将创建一个包含少量信息的查询在您选择的用户名下,无论是否是管理员。我们还没有创建 MenuF,所以让我们快速创建。不过,我们还没有完成 LoginF,所以请准备好稍后再谈!

创建表单,然后按下按钮。这是您的菜单表单,您可以根据需要创建任意数量的按钮到其他表单,甚至只需在此处放置一个子表单并拥有整个数据库。按下按钮,您可以将文本命名为任何您想要的名称。我把我的作为注销。将按钮命名为 MenuLogOutBtn。进入事件选项卡,在 On Click 脚本下单击代码并输入:

Private Sub MenuLogOutBtn_Click()
   DoCmd.DeleteObject acQuery, "IsAdminQ"
           DoCmd.OpenForm "LoginF"
           DoCmd.Close acForm, "MenuF", acSaveNo
End Sub

这样做是删除登录按钮创建的查询,再次打开登录表单,然后关闭菜单。简单!

现在我需要你扔下一个复选框,并将其命名为 MyCheckbox。此框不需要特殊编码或控制源。虽然我确实建议将可见更改为否,并删除随之而来的文本。

现在,转到表单的事件属性并在打开脚本下转到代码并输入:

Private Sub Form_Open(Cancel As Integer)

  Me.MyCheckbox.Value = GetLoginStateIsAdmin()

  If GetLoginStateIsAdmin = True Then
Me.ShortcutMenu = True
DoCmd.ShowToolbar "Ribbon", acToolbarYes
DoCmd.ShowToolbar "Menu Bar", acToolbarYes
Application.SetOption "ShowWindowsinTaskbar", True
DoCmd.SelectObject acTable, , True
  Else
Me.ShortcutMenu = False
DoCmd.ShowToolbar "Ribbon", acToolbarNo
DoCmd.ShowToolbar "Menu Bar", acToolbarNo
Application.SetOption "ShowWindowsinTaskbar", False
DoCmd.NavigateTo "acNavigationCategoryObjectType"
DoCmd.RunCommand acCmdWindowHide
  End If

End Sub

它的作用是附加到查询的IsAdmin 列的复选框信息,并为GetLoginStateIsAdmin 提供该布尔变量。之后,它会启动一个简单的 If 语句,如果您不是管理员,它会关闭菜单栏并禁用右键单击;如果你是,它允许你右键单击并且所有菜单栏都是可见的。

如果您还没有注意到,我们的复选框还没有从查询中获取信息!哦不!

第 3 步:创建公共模块

如果您小心翼翼,您会注意到此时连登录代码都不起作用。首先,我们需要一些公共模块。转到功能区中的“创建”选项卡,然后创建一个模块。输入:

    Public EmployeeID As Long

Save this module as LoginModule.

Create another module, and type this in:

    Function GetLoginStateIsAdmin()
    '
      Dim rst As DAO.Recordset

      Set rst = CurrentDb.OpenRecordset("IsAdminQ")
      GetLoginStateIsAdmin = Nz(rst(0), False)

      Set rst = Nothing
    '
    End Function

Save this one as GetAdmin.

Lets create one more module; so the user opening the database can't by bass stuff by using the shift key to launch it.

Type this in it:

Function ap_DisableShift()
'This function disable the shift at startup. This action causes
'the Autoexec macro and Startup properties to always be executed.

On Error GoTo errDisableShift

Dim db As DAO.Database
Dim prop As DAO.Property
Const conPropNotFound = 3270

Set db = CurrentDb()

'This next line disables the shift key on startup.
db.Properties("AllowByPassKey") = False

'The function is successful.
Exit Function

errDisableShift:
'The first part of this error routine creates the "AllowByPassKey
'property if it does not exist.
If Err = conPropNotFound Then
Set prop = db.CreateProperty("AllowByPassKey", _
dbBoolean, False)
db.Properties.Append prop
Resume Next
Else
MsgBox "Function 'ap_DisableShift' did not complete successfully."
Exit Function
End If

End Function

将其保存为 ShiftModule。

我们完成了模块!现在让我们回到 LoginF。

第 4 步:完成登录F

转到表单的事件选项卡,然后单击加载脚本。点击代码,然后输入:

Private Sub Form_Load()
   On Error Resume Next
   DoCmd.DeleteObject acQuery, "CustomerMoreInfoQ"
End Sub

这样做是为了确保在此表单启动时删除登录按钮创建的查询,以防用户在未注销的情况下关闭数据库。所以如果你点击登录,它不会导致错误,因为查询不在那里。

第 5 步:测试。

在表单视图中运行表单 LoginF,并选择 Bob 作为用户名。在密码文本框中输入密码 1234,然后单击登录。它应该打开 MenuF,您会看到所有菜单,您可以右键单击。好的。现在,注销并使用 Stewert 登录,使用相同的密码。现在您看到所有菜单都自行删除了,而且您无法右键单击!耶!

为了增加安全性,在 LoginF 的“其他”选项卡中,确保将快捷菜单设置为“否”。这会将右键单击设置为始终禁用;因为此时您还没有以用户身份登录。它不知道你是否是管理员。

第 6 步:在启动时禁用工具栏并在启动时启动 LoginF。

转到文件 > 选项 > 当前数据库。

在显示表单下,选择 FormF。 在导航部分下,取消单击显示导航窗格。

点击ok,然后返回LoginF;进入 On Load 代码并将其添加到 End Sub 之前:

DoCmd.ShowToolbar "Ribbon", acToolbarNo

你已经完成了!保存您的数据库,然后关闭它并再次打开它。它应该加载无法右键单击的 LoginF 表单,没有菜单等。让菜单编辑内容的唯一方法是登录管理员帐户!

第 7 步:展开

虽然您添加的表单越多,这不会自动扩展。您需要将名为 MyCheckbox 的复选框(我建议复制+粘贴)添加到您添加的每个表单中,并将此代码添加到您添加的每个表单中:

Private Sub Form_Open(Cancel As Integer)

  Me.MyCheckbox.Value = GetLoginStateIsAdmin()

  If GetLoginStateIsAdmin = True Then
Me.ShortcutMenu = True
  Else
Me.ShortcutMenu = False
  End If

End Sub

尽管对每个表单都执行了此操作,但安全性仍然有效,您需要登录管理员帐户才能更改任何内容。如果你只是一个用户,你可以正常使用表单(点击按钮,编辑子表单上的数据等)你不能编辑它自己的表单。

【讨论】:

  • 还要注意要向表中添加更多用户,您必须以管理员身份登录并手动添加它们(除非您采取此操作并进一步应用它,并制作一个具有子表单的表单它附加到表格中,可让您从表格中编辑表格,除非您登录管理员帐户,否则无法访问它。
  • 您的安全策略会阻止这种情况吗? ... UPDATE LogininfoT SET IsAdmin = True WHERE EmployeeName = 'Stewert'; ... 或者这个 ... SELECT LoginPassword FROM LogininfoT WHERE EmployeeName = 'Bob';
  • 不,但是当您完全启动数据库时,您无法编辑任何内容,因此您唯一能做的就是登录帐户。即使作为用户,您也无法添加或编辑 VBA。我确信我可以找到一种方法来针对这些添加预防措施,但我认为这不是必需的。
  • 这一切都归结为您所说的安全。 Stewert 可以打开与您的 db 文件的连接并执行UPDATE 以赋予自己管理员权限。或者更简单的是,他可以打开另一个 Access db 文件,链接到您的 LogininfoT 表,然后查看/编辑其中的任何内容。换句话说,这种安全策略很容易被打败。如果您的安全要求只是让用户做您不希望他们做的事情变得不那么方便,那么您可能没问题。
  • +1 写一篇好文章,把你的想法带到尽可能远的地方。 -1 因为我同意@HansUp 的观点,即这是为了最小的利益而做的大量工作。如果您的应用程序足够重要以确保安全,那么您应该适当地保护它,例如,通过将后端转换为 SQL Server Express 并在那里设置权限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 2011-08-18
相关资源
最近更新 更多