如何解决在 Linux(Ubuntu 18.04)中进行 EF Core 数据库脚手架的“无法使用 Kerberos 进行身份验证”问题?有啥解决办法吗?

Posted

技术标签:

【中文标题】如何解决在 Linux(Ubuntu 18.04)中进行 EF Core 数据库脚手架的“无法使用 Kerberos 进行身份验证”问题?有啥解决办法吗?【英文标题】:How to solve 'Cannot authenticate using Kerberos' issue doing EF Core database scaffolding in Linux(Ubuntu 18.04)? Are there any solutions?如何解决在 Linux(Ubuntu 18.04)中进行 EF Core 数据库脚手架的“无法使用 Kerberos 进行身份验证”问题?有什么解决办法吗? 【发布时间】:2020-04-02 14:00:01 【问题描述】:

每个人。我一直在尝试使用 EntityFrameworkCore 开发简单的启动 AspNetCore 应用程序,以连接和使用 MS SQL 服务器数据库。并通过 Rider IDE、数据库客户端工具 (DBeaver) 和 dotnet 命令行界面 (dotnet ef) 管理所有这些。我使用的是数据库优先方法(在 mssql 服务器上创建数据库,用表填充它,然后基于表构建模型)。我的分步操作:

1) 为我在 Ubuntu 18.04 上工作的机器安装和设置 mssql 服务器。安装命令行工具“SQLCMD”。 /// 指南链接 - https://docs.microsoft.com/en-gb/sql/linux/quickstart-install-connect-ubuntu?view=sql-server-ver15

2)本地连接到我的 MSSQLServer 实例。 sqlcmd -S localhost -U SA -P 'MyPasswd'

3) 使用 Transact-SQL 创建的数据库并安装数据库客户端 (DBeaver) 来快速管理我现在和将来的数据库。

按照我的设想,下一步是使用有关将我的 Web 应用程序连接到数据库的教程,这些教程可以在 https://blog.jetbrains.com/dotnet/2017/08/09/running-entity-framework-core-commands-rider/ 和 https://www.entityframeworktutorial.net/efcore/create-model-for-existing-database-in-ef-core.aspx 找到

我的 ASP.NET Core 项目的包参考:

Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.Tools

在输入 CLI 命令后 dotnet ef dbcontext 脚手架“服务器=本地主机;数据库=WebAppDB;集成安全=真;” Microsoft.EntityFrameworkCore.SqlServer -c RsvpContext ( 构建“RsvpContext”上下文以连接到我的数据库 WebAppDB。)

我看到了我所看到的:

Build started...
Build succeeded.
Microsoft.Data.SqlClient.SqlException (0x80131904): **Cannot authenticate using 
Kerberos. Ensure Kerberos has been initialized on the client with 'kinit' and a 
Service Principal Name has been registered for the SQL Server to allow Kerberos 
authentication.**

ErrorCode=InternalError, Exception=Interop+NetSecurityNative+GssApiException: 
GSSAPI operation failed with error - Unspecified GSS failure.  Minor code may 
provide more information (SPNEGO cannot find mechanisms to negotiate).


   at System.Net.Security.NegotiateStreamPal.GssInitSecurityContext(SafeGssContextHandle& context, SafeGssCredHandle credential, Boolean isNtlm, SafeGssNameHandle targetName, GssFlags inFlags, Byte[] buffer, Byte[]& outputBuffer, UInt32& outFlags, Int32& isNtlmUsed)

   at System.Net.Security.NegotiateStreamPal.EstablishSecurityContext(SafeFreeNegoCredentials credential, SafeDeleteContext& context, String targetName, ContextFlagsPal inFlags, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ContextFlagsPal& outFlags)

   at Microsoft.Data.SqlClient.SNI.SNIProxy.GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, Byte[] receivedBuff, Byte[]& sendBuff, Byte[] serverName)

   at Microsoft.Data.SqlClient.SNI.TdsParserStateObjectManaged.GenerateSspiClientContext(Byte[] receivedBuff, UInt32 receivedLength, Byte[]& sendBuff, UInt32& sendLength, Byte[] _sniSpnBuffer)

   at Microsoft.Data.SqlClient.TdsParser.SNISSPIData(Byte[] receivedBuff, UInt32 receivedLength, Byte[]& sendBuff, UInt32& sendLength)

   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken, DbConnectionPool pool, SqlAuthenticationProviderManager sqlAuthProviderManager)

   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)

   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)

   at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)

   at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)

   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)

   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)

at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)

   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)

   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)

   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)

   at Microsoft.Data.SqlClient.SqlConnection.Open()

   at Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal.SqlServerDatabaseModelFactory.Create(DbConnection connection, DatabaseModelFactoryOptions options)

at Microsoft.EntityFrameworkCore.SqlServer.Scaffolding.Internal.SqlServerDatabaseModelFactory.Create(String connectionString, DatabaseModelFactoryOptions options)

   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions)

   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames)

   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames)

   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0()

   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()

   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:38f805bc-5879-458b-9256-d6a201d7ce99
Cannot authenticate using Kerberos. Ensure Kerberos has been initialized on the 
client with 'kinit' and a Service Principal Name has been registered for the SQL 
Server to allow Kerberos authentication.
ErrorCode=InternalError, Exception=Interop+NetSecurityNative+GssApiException: 
GSSAPI operation failed with error - Unspecified GSS failure.  Minor code may 
provide more information (SPNEGO cannot find mechanisms to negotiate).

   at System.Net.Security.NegotiateStreamPal.GssInitSecurityContext(SafeGssContextHandle& context, SafeGssCredHandle credential, Boolean isNtlm, SafeGssNameHandle targetName, GssFlags inFlags, Byte[] buffer, Byte[]& outputBuffer, UInt32& outFlags, Int32& isNtlmUsed)

   at System.Net.Security.NegotiateStreamPal.EstablishSecurityContext(SafeFreeNegoCredentials credential, SafeDeleteContext& context, String targetName, ContextFlagsPal inFlags, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ContextFlagsPal& outFlags)

   at Microsoft.Data.SqlClient.SNI.SNIProxy.GenSspiClientContext(SspiClientContextStatus sspiClientContextStatus, Byte[] receivedBuff, Byte[]& sendBuff, Byte[] serverName)

   at Microsoft.Data.SqlClient.SNI.TdsParserStateObjectManaged.GenerateSspiClientContext(Byte[] receivedBuff, UInt32 receivedLength, Byte[]& sendBuff, UInt32& sendLength, Byte[] _sniSpnBuffer)

   at Microsoft.Data.SqlClient.TdsParser.SNISSPIData(Byte[] receivedBuff, UInt32 receivedLength, Byte[]& sendBuff, UInt32& sendLength)

如果有人(最好是在 Linux 上工作)遇到同样的问题,请告诉我并分享您的解决方案(有关在这种情况下该怎么做的指南)。

【问题讨论】:

在 Linux 服务器上配置 Kerboros 是一个漫长的过程,而且并不简单。简单的答案是在此处使用 SQL 身份验证。除非您非常熟悉 Linux 和 SQL Server,否则我不建议您尝试走 Kerboros 路线。 preferably working on Linux Windows 使用 Kerberos 进行 Windows 身份验证,其中配置由操作系统在加入域、机器启动等时自动执行。Linux 并非如此。您没有在问题中发布任何 Kerberos 配置步骤。机器是 AD 域的一部分吗? Kerberos 是否以其他方式配置? Ensure Kerberos has been initialized on the client with 'kinit' and a Service Principal Name has been registered for the SQL Server to allow Kerberos authentication.你这样做了吗? @PanagiotisKanavos,回答你的 1 个问题,我可以说没有配置通过 Kerberos 的连接,原因是在键入 SELECT auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@spid 后;控制台输出是 auth_scheme | SQL 这是来自博客docs.microsoft.com/en-us/sql/database-engine/configure-windows/… 我只是不知道下一步该做什么 【参考方案1】:

在我们的案例中,我们最近在从内部部署转换为 azure kubernetes 云解决方案时遇到了这个问题。

简短的回答,它与集成身份验证有关。

我们将集成安全性更改为 false,因此集成身份验证应类似于 (integrated security=false;),并且我们还在连接字符串 (User ID=YourProperUserName;Password=YourProperUserPassword;) 中提供了具有正确访问权限的用户名和密码。

问题解决了。

【讨论】:

除了上面的答案之外,如果您的连接字符串中存在 Trusted_Connection=True 。删除它。【参考方案2】:

在您的连接字符串中更改Integrated Security=false

【讨论】:

请不要重复回答。没用。

以上是关于如何解决在 Linux(Ubuntu 18.04)中进行 EF Core 数据库脚手架的“无法使用 Kerberos 进行身份验证”问题?有啥解决办法吗?的主要内容,如果未能解决你的问题,请参考以下文章

Ubuntu18.04下QT开发Android无法连接设备问题解决

Ubuntu18.04下QT开发Android无法连接设备问题解决

ubuntu18.04 蓝牙打开无效,解决办法升级内核

ubuntu18.04 蓝牙打开无效,解决办法升级内核

ubuntu18.04 蓝牙打开无效,解决办法升级内核

win10 远程登录Ubuntu 18.04错误