毫秒访问;如何在没有密码的情况下将其移至不可访问状态/无 DSN table

ms access; how to move it into inaccessible state / DSN-less table without password

我尝试使用内置的导入菜单将 tables 从一个已打开的 MS Access accdb 文件导入到一个新的 accdb 文件中,但我收到一条错误消息。
错误消息说 "admin" 用户已将文件设置为不可访问状态。 (这是我从匈牙利语翻译过来的)
所以我无法导入任何 table 或查询。

我想知道如何使用 VBA 代码以编程方式将 accdb 或 accde 文件移动到此不可访问状态。

背后的原因:我想分发一个前端 accde 文件,它可以保护自己免受任何人窃取 odbc 连接信息,例如 MySQL 服务器用户和密码。但是 Msysobjects table 可以导入到另一个访问文件中。
我可以在启动时创建 tables 和查询,并在应用程序关闭时删除它们,但是如何防止 table 和查询在 运行 时从它导入?
这种无法访问的状态会派上用场。
如果有其他方法可以阻止 table 导入其他访问文件,请告诉我。

* 编辑部分:*
设计视图技巧:

DoCmd.OpenForm "frmUnused",acDesign,,,,acHidden  

与 accdb 一起工作,table 导入在编辑时被锁定。正如预期的那样,不适用于 accde。

连接缓存方式:
适用于查询。
FIXED:无论我怎么努力,用户名和密码都已用 table 保存。我提供了一个没有用户名和密码的连接字符串,但它在将 tabledef 附加到集合后出现在连接字符串中。
方法 A 保存未提供的密码,方法 B 仅适用于手动登录。

备注: 我知道在 accde 中 VBA 中存储用户和密码不是最安全的选择,但是.. 1. 创建一个新用户在服务器端和分配角色可能会非常缓慢。 (另请参阅:官僚主义)2. 将服务器凭据移交给几千名用户也使社会工程更容易。
如果您在文本编辑器中打开 accde 文件,则可以查看 Const 值,甚至是 Private Const 值。改用函数来回显值。

实际用户名和密码已替换为以下文本。
LOGON PASS/FAIL 和 .Connect before/after 行是从 debug.print 输出中复制的。

我尝试了两种变体:

A: / 由 Albert D. Kallal 提议 /
* 删除所有 table 和查询,压缩和修复,然后重新启动应用程序。
* ? table测试:使用用户和密码测试登录,然后不使用 AddOneTable(MyCon)。
* 登录密码
* .Connect before = ODBC;DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Database=mesterlista
* .Connect = ODBC;DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Database=mesterlista;user=;password=;
* >> 已存储用户和密码。
* 修复:在 .append 之后,重新编辑 .Connect 并重新链接。

B: / 使用手动登录 /
* 删除所有 table 和查询,压缩和修复,然后重新启动应用程序。
* AddOneTable(MyCon) + MySQL Connector/ODBC 数据源配置 window
* .Connect before = ODBC;DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Database=mesterlista
* .Connect = ODBC;Driver=MySQL ODBC 5.3 Unicode Driver;SERVER=localhost;DATABASE=mesterlista;PORT=3306
* >> 请注意,{}在驱动程序名称中消失了,同时还出现了 PORT。
* 应用重启
* ? TestLogon("ODBC;Driver=MySQL ODBC 5.3 Unicode Driver;SERVER=localhost;DATABASE=mesterlista;PORT=3306" & ";user=;password=")
* 正确
* Table 不工作,MySQL Connector/ODBC 数据源配置 window 弹出。
* ? TestLogon("ODBC;Driver=MySQL ODBC 5.3 Unicode Driver;SERVER=localhost;DATABASE=mesterlista;PORT=3306") + MySQL Connector/ODBC 数据源配置window, 手动登录
* 正确
* Table 正在工作。
* >> 因此,如果您希望手动登录,此方法很好,但不适用于自动登录。

VBA 用于测试的代码:

Public Function tabletest()

  Dim MyConWithPassWord   As String
  Dim MyCon               As String

  MyCon = "ODBC;DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Database=mesterlista"
  MyConWithPassWord = MyCon & ";user=***;password=***"

   If TestLogon(MyConWithPassWord) = False Then
      Debug.Print "LOGON FAIL"
      Exit Function
   End If

   Debug.Print "LOGON PASS"
   AddOneTable (MyCon)

End Function

Public Function TestLogon(strCon As String) As Boolean

   On Error GoTo TestError

   Dim dbs          As DAO.Database
   Dim qdf          As DAO.QueryDef

   Set dbs = CurrentDb()
   Set qdf = dbs.CreateQueryDef("")

   qdf.Connect = strCon
   qdf.ReturnsRecords = False

   'Any VALID SQL statement that runs on server will work below.
   qdf.SQL = "SELECT 1;"
   qdf.Execute

   TestLogon = True

Exit Function

TestError:
   TestLogon = False

   Debug.Print Err.Number, Err.Description
   Debug.Print strCon

End Function


Public Function AddOneTable(strCon As String)
   On Error GoTo myerr

  Dim tdfcurrent As DAO.TableDef

  Dim LocalTable    As String      ' name of local table link
  Dim ServerTable   As String      ' name of table on SQL server

  LocalTable = "cimke"
  ServerTable = "cimke"

  Set tdfcurrent = CurrentDb.CreateTableDef(LocalTable)

  tdfcurrent.SourceTableName = ServerTable
  tdfcurrent.Connect = strCon

  Debug.Print ".Connect before = " & tdfcurrent.Connect

  CurrentDb.TableDefs.Append tdfcurrent

  CurrentDb.TableDefs.Refresh
  Debug.Print ".Connect after = " & CurrentDb.TableDefs(LocalTable).Connect

  ' fix: removing user / password from tabledef.connect:
  Set tdfcurrent = CurrentDb.TableDefs(LocalTable)
  tdfcurrent.Connect = strCon
  tdfcurrent.RefreshLink

  Debug.Print ".Connect after RELINK = " & CurrentDb.TableDefs(LocalTable).Connect



Exit Function

myerr:
   Debug.Print Err.Number, Err.Description
   Debug.Print strCon

End Function   

是的,你可以做到。

您不必在连接字符串中包含 UID + 密码。

这意味着在代码启动时您可以执行登录。您可以:

在您的 VBA 代码中嵌入登录。只需要在启动时登录一次,然后所有现有的 linked tables 都可以工作,即使 linked tables 没有'在这些连接字符串中包含用户名和密码。

并且如果您担心有人使用某种文件 HEX 编辑器等来解析或查看accDE 文件的上下文。

另一种简单的方法是在启动时提示用户名+密码(向用户询问用户名+密码)。此时,您只需执行登录即可。执行该登录后,所有 linked tables 都将正常工作,而那些 linked tables 不需要 UID+PASSOWRD被包含,也不会嵌入那些 linked tables.

我不能强调,如果您这样做,则不需要重新 link 的 tables。

上述原因和技巧是,一旦发生合法登录,access 将缓存登录。一旦发生登录(连接成功),所有其他 linked tables 将使用此缓存连接。

所以,我建议你删除所有你的linked tables,然后执行一次登录,然后重新link所有的tables并在执行此操作时省略用户名和密码。 (请记住不要在用于 link 和 table 的连接字符串中包含用户 + 密码。您可以使用内置的 table 管理器来执行此操作,或者您可以使用代码– 两种方式都行。

一旦您 link 以这种方式启动应用程序,table link 将不起作用,它们仅在您执行登录后才起作用。

这意味着如果有人试图打开或导入 table links 到另一个数据库,linked tables 将无法工作,因为linked tables 不包括用户 + 密码。

要执行登录,请使用以下代码:

strCon = "valid connection string PLUS USERID + PASSWORD"

因此,使用现有的连接字符串(没有 userID/password),将 userid/password 添加到字符串中,然后像这样执行登录代码:

TestLogon(strCon)

执行登录的代码如下:

Function TestLogin(strCon As String) As Boolean

  On Error GoTo TestError

  Dim dbs          As DAO.Database
  Dim qdf          As DAO.QueryDef

  Set dbs = CurrentDb()
  Set qdf = dbs.CreateQueryDef("")

   qdf.connect = strCon

   qdf.ReturnsRecords = False

   'Any VALID SQL statement that runs on server will work below.

   qdf.sql = "SELECT 1 as t"
   qdf.Execute

   TestLogin = True

   Exit Function

TestError:
    TestLogin = False
    Exit Function

End Function

一旦你执行了上面的操作,那么 linked tables 没有用户 + 密码现在就可以工作了!

如果有人试图打开或导入 table link,则不会包含用户 + 密码,您也不想在连接字符串中包含用户 + 密码习惯了link table.

所以删除你的 table link。执行上面的登录代码。现在重新 link tables – 但不要选择包含用户 + 密码的选项。

如果您跳过上面的登录代码,并尝试打开 table,那么 ODBC 驱动程序将提示您输入用户 ID + 密码。 (所以你得到什么样的提示将取决于数据库供应商如何设置他们的 odbc 驱动程序来处理这个问题。

以上就是您所需要的。以下文章概述了上述代码的“想法”及其工作原理:

https://blogs.office.com/en-us/2011/04/08/power-tip-improve-the-security-of-database-connections/

然而,相同的代码和上面的解释应该足够了。

您不必在 linked table 中包含用户 ID + 密码,出于明显的安全原因,您不应该这样做。

请记住,几乎所有客户端软件都需要一些登录,但如果您不在代码中的任何位置嵌入 uid/password,那么 linked 的安全漏洞就会很大Access中的tables被淘汰。如果有人试图反汇编应用程序,获取 linked table 连接字符串等,他们将不会获得密码。因此,如果有人在启动时提示,登录,然后清空这些值,那么 uid/password 再次没有嵌入到应用程序中。

任何人都可以反汇编代码,如果您在 Access 中遵循此方法,他们将无法获得 uid/password。

如果用户导入那些 link,并且他们在普通视图中有 uid/password,那么他们将看到 uid/password。但是,如果您 link table 而没有 uid/password,则无需在应用程序中的任何位置嵌入 uid/password 即可工作。所需要做的就是使用上述代码执行有效登录 - 一旦完成,所有连接都将正常工作。

因此,在执行登录之前或之后,linked table 绝不会显示或显示 uid/password。事实上,这甚至包括是否使用 accDB(非编译应用程序)。如果您跳转到调试 window 并检查用于活动工作 linked tables 的连接字符串,您将看到 uid/password 不包含在连接中字符串!

绝大多数客户端软件系统确实必须连接到数据库,如果在该代码或应用程序中的任何地方都没有包含 uid/password,那么这是 "reasonable" 级别的安全。

这是我使用的一些示例代码:

Sub TEst222()

  Dim MyConWithPassWord   As String
  Dim MyCon               As String

  MyCon = "ODBC;DRIVER=SQL Server;SERVER=albertkallal-pc\SQLEXPRESS;DATABASE=test3"

  MyConWithPassWord = MyCon & ";UID=TEST3;pwd=password"

  TestLogon (MyConWithPassWord)
  AddOneTable (MyCon)

End Sub

使用的 TestLogon 是:

Function TestLogon(strCon As String) As Boolean

  On Error GoTo TestError

  Dim dbs          As DAO.Database
  Dim qdf          As DAO.QueryDef

  Set dbs = CurrentDb()
  Set qdf = dbs.CreateQueryDef("")

   qdf.Connect = strCon
   qdf.ReturnsRecords = False

   'Any VALID SQL statement that runs on server will work below.

   qdf.SQL = "SELECT 1"

   qdf.Execute

   TestLogon = True

Exit Function

TestError:
   TestLogon = False
   Exit Function

End Function

并添加一个 table link:

Sub AddOneTable(strCon As String)

  Dim tdfcurrent As DAO.tableDef

  Dim LocalTable    As String      ' name of local table link
  Dim ServerTable   As String      ' name of table on SQL server

  LocalTable = "MyTable"
  ServerTable = "dbo.MyTable"

  Set tdfcurrent = CurrentDb.CreateTableDef(LocalTable)

  tdfcurrent.SourceTableName = ServerTable
  tdfcurrent.Connect = strCon
  CurrentDb.TableDefs.Append tdfcurrent

End Sub

我的示例代码适用于 SQL 服务器。不过我上面link的文章还是不错的,示例代码是MySQL.

这是一个 MySQL 示例:

Dim MyConWithPassWord   As String
Dim MyCon               As String

MyCon = "ODBC;DRIVER={MySQL ODBC 3.51 Driver};Server=localhost;Database=test3"

MyConWithPassWord = MyCon & ";User=TEST3;Password=TEST3"

If TestLogon(MyConWithPassWord) = False Then
   MsgBox "LOGON FAIL"
   Exit Sub
End If

AddOneTable (MyCon)

所以您需要测试您是否真的登录了(这是本 post 的重点)。

如果您在重新 link 期间收到提示,则表示您所拥有的无法正常工作。这里的重点是消除登录的需要。

一旦成功。您可以启动 Access,然后双击 table - 将提示 ODBC 登录。但是,如果您先执行登录代码,则可以在没有 odbc 登录提示的情况下单击 table。