【问题标题】:Npgsql error after changing Windows Local Network Security policy更改 Windows 本地网络安全策略后出现 Npgsql 错误
【发布时间】:2016-02-22 21:07:33
【问题描述】:

我们公司最近开始与一个合作伙伴开展业务,该合作伙伴试图为我们提供一个基于 Web 的 RDP 连接到他们的系统中。作为他们设置文档的一部分,他们要求我们更改工作站的本地网络安全策略:具体来说,从之前的 Send LM 更改 LAN Manager 身份验证级别设置& NTLM 响应仅发送 NTLMv2 响应。一旦我做出此更改并 gpupdate /force 对工作站进行更改(然后显示“正确”设置的策略),我可以 RDP 进入我们新合作伙伴的服务器就好了,但我所有的应用程序连接到 PostgreSQL 数据库文件,出现以下错误:

FATAL: XX000: could not accept SSPI security context

我已经构建了一个临时应用程序,以使用以下代码在 Visual Studio 中测试连接(网络详细信息已编辑):

Imports Npgsql
Imports System.DirectoryServices

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim PGUserName As String
        Dim PGDB As NpgsqlConnection = Nothing
        Dim PGConnection As NpgsqlConnectionStringBuilder
        Dim PGCommand As NpgsqlCommand = Nothing
        Dim PGAdapter As NpgsqlDataAdapter = Nothing
        Dim TestSQL As String = String.Empty
        Dim TestData As New DataTable

        PGUserName = GetActiveDirectoryUsername()

        TestSQL = "SELECT * FROM testdb"
        PGConnection = New NpgsqlConnectionStringBuilder

        With PGConnection
            NpgsqlEventLog.Level = LogLevel.Debug
            NpgsqlEventLog.LogName = "C:\TEST\NPGSQLEVENTLOG.TXT"
            .Host = "<PGSQLSERVER>"
            .Port = <PORT>
            .UserName = PGUserName
            .IntegratedSecurity = True
            .Database = "testing"
        End With

        PGDB = New NpgsqlConnection(PGConnection.ConnectionString)

       Try
            PGDB.Open()
            PGCommand = New NpgsqlCommand(TestSQL, PGDB)
            PGAdapter = New NpgsqlDataAdapter(PGCommand)
            PGAdapter.Fill(TestData)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            If Not PGAdapter Is Nothing Then
                PGAdapter.Dispose()
            End If

            If Not PGCommand Is Nothing Then
                PGCommand.Dispose()
            End If

            If PGDB.State <> ConnectionState.Closed Then
                PGDB.Close()
            End If

            If Not PGDB Is Nothing Then
                PGDB.Dispose()
            End If

            If Not TestData Is Nothing Then
                TestData.Dispose()
            End If
        End Try
    End Sub

    Friend Function GetDirectoryEntry() As DirectoryEntry
        Dim dirEntry As DirectoryEntry = New DirectoryEntry()
        dirEntry.Path = "LDAP://<ADSERVERIP>/DC=<DOMAIN>"
        Return dirEntry
    End Function

    Friend Function GetActiveDirectoryUsername() As String
        Try
            Dim MyDirectory As DirectoryEntry = GetDirectoryEntry()
            Dim search As New DirectorySearcher(MyDirectory)

            search.Filter = String.Format("(&(SAMAccountName={0}))", Environment.UserName)

            'Use the .FindOne() Method to stop as soon as a match is found
            Dim result As SearchResult = search.FindOne()

            If result Is Nothing Then
                Return ""
            Else
                Return result.Properties("samaccountname").Item(0).ToString
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Active Directory Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)
            Return ""
        End Try
    End Function
End Class

如果我在发送 LM 和 NTLM 响应 上设置 LAN Manager 身份验证级别,所有这些代码都可以正常工作,但如果我改变它按照我们的新合作伙伴的要求仅发送 NTLMv2 响应,它会在 PGDB.Open() 语句上引发异常。来自调试日志:

2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlConnection.NpgsqlConnection(NpgsqlConnection())
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: HOST = <PGSQLSERVER>
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: PORT = <PORT>
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: PROTOCOL = 3
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: DATABASE = testing
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: USER ID = <PGSQLUSERNAME>
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: SSL = False
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: SSLMODE = Disable
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: TIMEOUT = 15
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: POOLING = True
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: CONNECTIONLIFETIME = 15
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: MINPOOLSIZE = 1
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: MAXPOOLSIZE = 20
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: SYNCNOTIFICATION = False
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: COMMANDTIMEOUT = 20
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: ENLIST = False
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: PRELOADREADER = False
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: USEEXTENDEDTYPES = False
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: INTEGRATED SECURITY = True
2/22/16 12:32:58 PM 11452   Debug   ConnectionString Option: COMPATIBLE = 2.0.11.92
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlConnection.Open()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlClosedState.Instance
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlClosedState.Instance
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlClosedState.Open()
2/22/16 12:32:58 PM 11452   Debug   Attempt to connect to '<PGSQLSERVERIP>'.
2/22/16 12:32:58 PM 11452   Normal  Connected to: <PGSQLSERVER>:<PORT>.
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlStartupPacket.NpgsqlStartupPacket()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlStartupPacket.WriteToStream()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlStartupPacket.WriteToStream_Ver_3()
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: user.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: <PGSQLUSERNAME>.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: database.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: testing.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: DateStyle.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteString()
2/22/16 12:32:58 PM 11452   Debug   String written: ISO.
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlState.ProcessBackendResponses()
2/22/16 12:32:58 PM 11452   Debug   AuthenticationRequest message received from server.
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlStartupState.Authenticate()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlPasswordPacket.NpgsqlPasswordPacket()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlPasswordPacket.WriteToStream()
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteBytes()
2/22/16 12:32:58 PM 11452   Debug   Unable to find resource string Log_BytesWritten for class PGUtil
2/22/16 12:32:58 PM 11452   Debug   AuthenticationRequest message received from server.
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlStartupState.Authenticate()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlPasswordPacket.NpgsqlPasswordPacket()
2/22/16 12:32:58 PM 11452   Debug   Entering NpgsqlPasswordPacket.WriteToStream()
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.WriteBytes()
2/22/16 12:32:58 PM 11452   Debug   Unable to find resource string Log_BytesWritten for class PGUtil
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: FATAL.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: XX000.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: could not accept SSPI security context.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: The token supplied to the function is invalid
 (80090308).
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: src\backend\libpq\auth.c.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: 1024.
2/22/16 12:32:58 PM 11452   Debug   Entering PGUtil.ReadString()
2/22/16 12:32:58 PM 11452   Debug   Get NpgsqlEventLog.LogLevel
2/22/16 12:32:58 PM 11452   Debug   String read: pg_SSPI_error.
2/22/16 12:32:58 PM 11452   Debug   ErrorResponse message from Server: could not accept SSPI security context.
2/22/16 12:32:58 PM 11452   Normal  An NpgsqlException occured: FATAL: XX000: could not accept SSPI security context.
2/22/16 12:33:02 PM 11452   Debug   Entering NpgsqlConnection.Dispose()
2/22/16 12:33:03 PM 11452   Debug   Entering NpgsqlConnection.Close()

奇怪的是,如果我尝试使用 SSPI 使用 PGAdmin III 进行连接,则没有错误。我重新启动了服务器上的 PostgreSQL 服务(以防万一),但仍然出现同样的错误。我什至重启了整个服务器,但错误仍然存​​在。

现在,如果我将本地网络安全策略设置改回 发送 LM 和 NTLM 响应,应用程序可以正常工作,但我们无法建立 RDP 连接到我们合作伙伴的系统。我什至尝试将策略设置更改为发送 LM 和 NTLM - 如果协商则使用 NTLMv2 会话安全。同样,我的应用程序将无错误地连接到数据库,但 RDP 连接失败。

我想问题归结为:当本地网络安全策略的 LAN 管理器身份验证级别设置配置为 只发送 NTLMv2 响应?由于其他一切似乎都正常工作(据我所知),这似乎是失败的地方。

编辑:由于我在 Visual Studio 2015 中工作,因此我尝试通过 NuGet 控制台更新我正在使用的 Npgsql 版本。这将库更新到版本 3.0.5.0,我在 仅发送 NTLMv2 响应 设置下再次测试了连接。这次应用程序的连接似乎工作正常。可以肯定的是,我删除了 3.0.5.0 引用并添加了我的旧版本(显然我在 2.0.11.92 - 是的,是的......我知道)并再次测试,这给了我和以前一样的错误。

看起来导致问题的任何原因都已通过对 Npgsql 库的后续更新得到解决。当然,这意味着,除非我正在使用的版本 (2.0.11.92) 有解决方法,否则我将不得不更新所有内部应用程序以使用更新的库。我真的现在没有时间做所有这些,所以如果有人有办法完成这项工作,我很想听听。

【问题讨论】:

    标签: vb.net postgresql security npgsql ntlmv2


    【解决方案1】:

    @G_Hosa_Phat。 我记得我们对 ntlm 支持做了很大的修改,你可以通过测试最近的 3.0.x 版本来检查它并让它工作......

    没有配置选项可以更改您可以使用的 ntlm 身份验证的行为。 我认为您确实需要更新您的库。

    但我建议您更新到最新的 2.x 版本,而不是 3.0.x,因为 3.0.x 的更改超出了 ntlm 支持,它可能会破坏您现有的系统。

    很抱歉告诉你这个坏消息。 :(

    希望对你有帮助。

    【讨论】:

    • 感谢您提供的信息。除非我们的新合作伙伴可以给我一条通往他们系统的替代路线,否则我想是时候开始更新和测试我的内部应用程序了。他们只有大约 50 个……哦,好吧。
    • @FranciscoJunior 我发现 2.2.7 版本(NuGet 网站 [nuget.org/packages/Npgsql] 上提供的最新 2.x 版本)可能会是这样去。我的一些应用程序是在 VS2008 中构建的,其中可用的最高 .NET 框架是 3.5。当我尝试将 3.0.5 版本添加到这些时,它找不到必要的参考。这意味着我可以在较新的 VS2015 下重建所有内容以使用最新的 Npgsql 版本,或者我可以使用 2.2.7 版本“回退并踢”。猜猜我现在选择哪一个。 :-P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2021-02-12
    相关资源
    最近更新 更多