【问题标题】:Forcing Access to forget a username and password for a linked table强制访问忘记链接表的用户名和密码
【发布时间】:2019-04-18 09:59:37
【问题描述】:

我有一个 MS Access 数据库,它通过链接服务器连接到 SQL 服务器。

链接表是使用修改后的AttachDSNLessTable 过程添加的:

stConnect = "ODBC;DRIVER=" & stDriverName & ";SERVER=" & stServer & ";DATABASE=" & stDatabase & ";UID=" & stUsername & ";PWD=" & stPassword
Set td = CurrentDb.CreateTableDef(stLocalTableName)
td.SourceTableName = stRemoteTableName
td.Connect = stConnect

CurrentDb.TableDefs.Append td

我在应用程序中有一个工具可以更改登录用户,这将删除所有 tabledef:

For Each td In CurrentDb.TableDefs
    If td.Name = stLocalTableName Then
        CurrentDb.TableDefs.Delete stLocalTableName
    End If
Next

然后它会使用上面的过程重新添加。

现在这似乎可以工作,但是如果我以user1 登录然后将用户更改为user2 而不关闭访问,则使用user1 凭据建立连接,运行包含SUSER_NAME() 的视图显示user1是登录用户。

有没有办法强制重置连接或强制更改用户?

编辑

我的整个登录功能:

Function AttachDSNLessTable(stLocalTableName As String, stRemoteTableName As String, stDriverName As String, stServer As String, stDatabase As String, Optional stUsername As String, Optional stPassword As String)
    On Error GoTo AttachDSNLessTable_Err
    Dim td As TableDef
    Dim stConnect As String

    For Each td In CurrentDb.TableDefs
        If td.Name = stLocalTableName Then
            CurrentDb.TableDefs.Delete stLocalTableName
            Exit For
        End If
    Next

    If Len(stUsername) = 0 Then
        '//Use trusted authentication if stUsername is not supplied.
        stConnect = "ODBC;DRIVER=" & stDriverName & ";SERVER=" & stServer & ";DATABASE=" & stDatabase & ";Trusted_Connection=Yes"
    Else
        '//WARNING: This will save the username and the password with the linked table information.
        stConnect = "ODBC;DRIVER=" & stDriverName & ";SERVER=" & stServer & ";DATABASE=" & stDatabase & ";UID=" & stUsername & ";PWD=" & stPassword
    End If

    Set td = CurrentDb.CreateTableDef(stLocalTableName)
    td.SourceTableName = stRemoteTableName
    td.Connect = stConnect

    CurrentDb.TableDefs.Append td
    AttachDSNLessTable = ""
    Exit Function

AttachDSNLessTable_Err:

    AttachDSNLessTable = err.Description

End Function

【问题讨论】:

  • @AndyG 导航面板上有一个“更改用户”选项,这会重新打开登录表单。当用户登录时,它使用第二个代码块删除 tabledef 对象并使用新的用户/密码重新添加它们,但它实际上是使用原始用户/密码打开连接。
  • 另外,一般用户可以使用这个功能吗?他们应该能够在不先退出的情况下切换用户名吗?
  • @AndyG 是的,它适用于任何用户。
  • Access 不适合这个,但是,在我看来,您的一般用户 / Joe 不应该能够在不退出 Access 的情况下切换用户。否则,如前所述,在更改用户的过程中可以重置连接。
  • @AndyG 我同意,Access 不合适,但无法更改。你知道如何重置连接吗?

标签: sql-server vba ms-access azure-sql-database


【解决方案1】:

编辑

我花了一段时间才意识到这一点。您的问题是 Access 缓存每个 {server,database} 基础的连接。没有办法清除这个缓存(据我所知)

但是有一种解决方法:即使服务器或数据库详细信息没有更改,答案也是使连接唯一。

使用 DSN 文件 您不能更改数据库名称或服务器名称以使连接唯一,但您可以更改 DSN 文件名,Access 会将连接视为“唯一”/新连接。

如果您使用相同的 DSN 文件,连接将再次被缓存,因此您必须为每次登录尝试使用不同的 DSN 文件。

这是一个通用功能,允许用户登录或注销您的系统。每次登录都会生成一个新的 DNS 文件并与您的数据库建立新连接 => 允许您登录的用户成为新用户。

以下函数只是概念性的。根据你的需要改变 并添加错误陷阱。

Public Function FN_CREATE_DNS_FILE()


    Const Server    As String = "" ' Server
    Const Driver    As String = "" ' Driver
    Const Port      As String = "" ' Port
    Const Database  As String = "" ' Database

    Dim DsnFileName As String
    Dim Fso         As Object
    Dim DnsFile     As Object

    Set Fso = CreateObject("Scripting.FileSystemObject")
    DsnFileName = VBA.Environ$("temp") & "\" & VBA.Format(Now(), "yyyy-mm-dd_hh_mm_ss") & ".dsn"

    Set DnsFile = Fso.CreateTextFile(DsnFileName)
    DnsFile.WriteLine "[ODBC]"
    DnsFile.WriteLine "DRIVER=" & Driver
    DnsFile.WriteLine "PORT=" & Port
    DnsFile.WriteLine "DATABASE=" & Database
    DnsFile.WriteLine "SERVER=" & Server

    'Close file and clean up
    DnsFile.Close
    Set Fso = Nothing
    Set DnsFile = Nothing

    FN_CREATE_DNS_FILE = DsnFileName

End Function

Public Function LogOut()

    Dim Qdf         As QueryDef

    For Each Qdf In CurrentDb.QueryDefs
        If (VBA.InStr(Qdf.Connect, "ODBC")) > 0 Then
            Qdf.Connect = "ODBC;" 'Either delete if you don't require this object or set to blank connection string
        End If
    Next Qdf

End Function



Public Function LogIn(stUsername As String, stPassword As String)

    Dim Tdf         As TableDef
    Dim Qdf         As QueryDef
    Dim stConnect   As String
    Dim ConForQuery As String
    Dim I           As Integer: I = 0

    Dim DsnFileName As String

    On Error GoTo AttachDSNLessTable_Err
    'Produce new DNS file with new filename to make Acces Connection unique
    DsnFileName = FN_CREATE_DNS_FILE()

    stConnect = "ODBC;AUTO_RECONNECT=1;NO_PROMPT=1"
    If Len(stUsername) = 0 Then
        '//Use trusted authentication if stUsername is not supplied.
        stConnect = stConnect & ";Trusted_Connection=Yes"
        ConForQuery = stConnect
    Else
        '//WARNING: This will save the username and the password with the linked table information.
        stConnect = stConnect & ";UID=" & stUsername & ";PWD=" & stPassword
        ConForQuery = stConnect & ";UID=" & stUsername
    End If

    ConForQuery = ConForQuery & ";" & "FILEDSN=" & DsnFileName
    stConnect = stConnect & ";" & "FILEDSN=" & DsnFileName

    On Error GoTo ERROR_Invalid_login
    'Update all linked tables
    For Each Tdf In CurrentDb.TableDefs
        If (VBA.InStr(Tdf.Connect, "ODBC")) > 0 Then
            Tdf.Connect = stConnect & ";TABLE=" & Tdf.Name
            If (I = 0) Then Tdf.RefreshLink 'Refreshing one table is enough as long as table definition hasnt changed
            I = I + 1
        End If
    Next Tdf

    'update all passthrough queries
    For Each Qdf In CurrentDb.QueryDefs
        If (VBA.InStr(Qdf.Connect, "ODBC")) > 0 Then
            Qdf.Connect = stConnect
        End If
    Next Qdf

    LogIn = ""
    Exit Function

AttachDSNLessTable_Err:
    LogIn = Err.Description
    Exit Function

ERROR_Invalid_login:
    LogIn = "Login failed"
    LogOut 'Delete or set blank for all pass through queries
End Function

如果用户登录,您只需调用

LogIn(Username, password)

这将更新所有链接表以及直通查询。

这是一个屏幕截图。

QryCurrentUser 执行 MySQL 命令select user();,显示当前连接的所有者。 如您所见,现在每个登录都显示正确的登录用户名。

如果登录失败,您有两种选择。删除表和直通查询中的所有链接。或将它们设置为空白连接字符串。

附言 我已将 NO_PROMPT & AUTO_RECONNECT 添加到连接字符串中,以防止在登录失败时显示数据库连接窗口并自动重新连接(MySQL 命令,不确定它是否适用于 MSSQL)如果不兼容则删除它们。

如果你能做到这一点,请告诉我。

【讨论】:

  • 我已将登录功能添加到问题中以解决问题。
  • 我正在删除 tabledef 并重新添加以避免将用户名和密码保存到数据库中。否则当它关闭并重新打开时,文件表会保留最后连接的用户,这是一个安全风险。
  • @bendataclear 您不需要为所有活动连接提供用户名和密码。只能连接一个表,其余表不需要用户名和密码。
  • 对不起,我没有关注,打电话Tdf.RefreshLink会使用新的用户名和密码吗?因为删除并重新添加 Tdf 不会。
  • @bendataclear。是的。默认情况下链接在表中不保存密码。关闭您的数据库而不删除表。打开访问,不要登录。现在检查链接表的 .connect 属性。您不会看到密码或用户 ID。
【解决方案2】:

有几个想法可以尝试。我只推荐这些,因为它们很容易检查。

  1. 尝试先重命名旧表,然后创建新表,然后删除旧表。如果您欺骗 Access 以为您是在添加而不是替换,它可能会配合。

  2. 尝试将另一个元素添加到连接字符串(除了 UID,Access 以特殊方式处理它)以使其每个用户唯一。我相信您可以将任意标记/值对添加到 ODBC 连接字符串,它会被忽略。例如

    "ODBC;Driver=SQL Server;MyUniqueTag=" & stUserName & ";UID=" & stUserName
    

    ODBC 连接池对于每个连接字符串都是唯一的,因此这可能会欺骗 Access 使用不同的连接池,因为它不知道 ODBC 驱动程序不使用MyUniqueTag

【讨论】:

  • 我在需要两组权限的 DB2 数据库中尝试了这种方法,但 Access 会在链接表时删除唯一标记。
猜你喜欢
  • 2012-04-13
  • 1970-01-01
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
相关资源
最近更新 更多