强制Access忘记链接表的用户名和密码

时间:2018-11-15 10:15:00

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

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

使用修改后的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而没有关闭Access,则使用user1凭据建立连接,并运行包含{ {1}}显示SUSER_NAME()是已登录的用户。

是否有任何方法可以强制重置连接或强制更改用户?

修改

我的整个登录功能:

user1

2 个答案:

答案 0 :(得分: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)

这将更新所有链接表以及传递查询。

这是屏幕截图。 Different user

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

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

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

让我知道您是否能够实现这一目标。

答案 1 :(得分:0)

可以尝试几种方法。我只建议这些,因为它们很容易检查。

  1. 尝试重命名旧表,然后创建新表,然后删除旧表。如果您使Access误以为您要添加而不是替换,它可能会起作用。

  2. 请尝试向连接字符串中添加另一个元素(UID除外,Access会对UID进行特殊处理),以使每个用户唯一。我相信您可以在ODBC连接字符串中添加任意标记/值对,并且它会被忽略。例如

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

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