You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行dotnet ef database update时遭遇SSL握手错误求助

ASP.NET EF Core迁移更新数据库时SSL/TLS握手失败问题(Arch Linux + VS Code)

在Arch Linux的VS Code(1.74.3版本)中开发ASP.NET项目,已成功通过dotnet ef migrations add生成迁移脚本,但执行dotnet ef database update -c PersistedGrantDbContext更新数据库时,出现SSL/TLS握手失败错误,提示预登录握手阶段加密失败。同时VS Code的mssql扩展也报相同SSL错误,但已部署的ASP.NET应用连接数据库正常。


环境详情

Version: 1.74.3
Commit: 97dec172d3256f8ca4bfb2143f3f76b503ca0534
Date: 2023-01-11T09:00:07.949Z
Electron: 19.1.9
Chromium: 102.0.5005.167
Node.js: 16.14.2
V8: 10.2.154.15-electron.0
OS: Linux x64 6.0.10-arch2-1
Sandboxed: No

执行命令

dotnet ef database update -c PersistedGrantDbContext

错误堆栈信息

Build started...
Build succeeded.
Microsoft.Data.SqlClient.SqlException (0x80131904): 已成功与服务器建立连接,但在预登录握手期间发生错误。(provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)
---> System.IO.IOException: 从传输流收到意外的EOF或0字节。
at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](CancellationToken cancellationToken)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
at Microsoft.Data.SqlClient.SNI.SNITCPHandle.EnableSsl(UInt32 options)
at Microsoft.Data.SqlClient.SNI.TdsParserStateObjectManaged.EnableSsl(UInt32& info, Boolean tlsFirst)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParser.EnableSsl(UInt32 info, SqlConnectionEncryptOption encrypt, Boolean integratedSecurity) at Microsoft.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(SqlConnectionEncryptOption encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean& marsCapable, Boolean& fedAuthRequired, Boolean tlsFirst) at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnectionString connectionOptions, Boolean withFailover) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) 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) at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions) 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, SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp) at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.b__0(DbContext _, TState s)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists(Boolean retryOnNotExists)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists()
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:461d4248-1aeb-4d6c-8964-f7864a2468c9
已成功与服务器建立连接,但在预登录握手期间发生错误。(provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)

PersistedGrantDbContextFactory.cs代码

using Duende.IdentityServer.EntityFramework.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace IdentityServer.Database
{
    public class PersistedGrantDbContextFactory : IDesignTimeDbContextFactory<PersistedGrantDbContext>
    {
        private readonly IConfiguration? _configuration;
        public PersistedGrantDbContextFactory()
        {
            _configuration = null;
        }
        public PersistedGrantDbContextFactory(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        PersistedGrantDbContext IDesignTimeDbContextFactory<PersistedGrantDbContext>.CreateDbContext(string[] args)
        {           
            string? cs = _configuration.GetConnectionString("Identity01");
            string? assemblyName = typeof(PersistedGrantDbContextFactory).Assembly.GetName().Name;

            var optionsBuilder = new DbContextOptionsBuilder<PersistedGrantDbContext>();
            optionsBuilder.UseSqlServer(cs);

            IServiceCollection services = new ServiceCollection();

            services.AddIdentityServer()
                    .AddOperationalStore(options =>
                    {
                        options.ConfigureDbContext = b => b.UseSqlServer(cs, sqlOptions =>
                        {
                            sqlOptions.MigrationsAssembly(assemblyName);
                        });
                    });

            optionsBuilder.UseApplicationServiceProvider(services.BuildServiceProvider());

            var context = new PersistedGrantDbContext(optionsBuilder.Options);
            return context;
        }
    }
}

连接字符串

"Data Source=ip,port;Initial Catalog=IdentityDb;Integrated Security=False;Persist Security Info=True;User ID=userName;Password=pass;Pooling=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=30;MultipleActiveResultSets=True;App=EntityFramework;"

解决方案

1. 强制使用TLS 1.2执行命令

Arch Linux上的.NET SDK可能默认启用较新TLS版本,而SQL Server不支持。执行命令前设置环境变量:

export DOTNET_SYSTEM_NET_SECURITY_ENABLETLS12=true
dotnet ef database update -c PersistedGrantDbContext

2. 显式配置SQL Server连接的SSL选项

修改PersistedGrantDbContextFactory中UseSqlServer的配置,确保SSL参数生效:

optionsBuilder.UseSqlServer(cs, o =>
{
    o.MigrationsAssembly(assemblyName);
    o.TrustServerCertificate(true);
    o.Encrypt(SqlServerEncryptOption.Disabled);
});

3. 更新Microsoft.Data.SqlClient包

旧版本的Microsoft.Data.SqlClient在Linux下可能存在SSL握手问题,更新到最新稳定版:

dotnet add package Microsoft.Data.SqlClient --version latest

4. 修复系统CA证书配置

确保系统CA证书安装并更新:

sudo pacman -Syu ca-certificates
sudo update-ca-trust

5. 调整VS Code mssql扩展的SSL设置

打开VS Code设置,搜索以下选项并修改:

  • mssql.encrypt 设置为 false
  • mssql.trustServerCertificate 设置为 true
    保存后重新连接数据库。

内容的提问来源于stack exchange,提问作者mohsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:25:59