EF Core为何使用Domain\MachineName而非连接字符串指定的User Id?
问题
使用EF Core时,SQL查询发送了错误的SQL身份验证用户名。
我们收到错误“Login failed for user '{DOMAIN}{MACHINE NAME}'”,而非使用连接字符串中指定的{DOMAIN}{User Id}。

连接字符串配置如下:
"Database": "Server=data.example.com;Database=example_data;Trusted_Connection=true;encrypt=no; user id=example; pwd=examplepassword;MultipleActiveResultSets=true"
但日志中显示的错误信息如下:
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user 'Domain\MachineName$'. 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.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK) 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.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, SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.Open() 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.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() ClientConnectionId:2e167322-21d0-47ab-bc9b-8d900fec060e Error Number:18456,State:1,Class:14
应用程序部署在IIS上,已启用匿名身份验证,禁用Windows身份验证。
额外代码片段
Program.cs
using LoadingBlazorWebAssemblyApp.Server.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); builder.Services.ConfigureDataContexts(builder.Configuration); var app = builder.Build(); if (app.Environment.IsDevelopment() || app.Environment.IsEnvironment("Test")) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.MapRazorPages(); app.MapControllers(); app.MapFallbackToFile("index.html"); app.Run();
DB Context注册
services.AddDbContext<DataContext>(options => options.UseSqlServer(configuration.GetConnectionString("Database"), s => s.CommandTimeout(180)) .ConfigureWarnings(warning => warning.Ignore(CoreEventId.StartedTracking)) .LogTo(message => Debug.WriteLine(message)) .EnableSensitiveDataLogging());
提供程序及版本信息
- EF Core版本:7.0.3
- 数据库提供程序:Microsoft.EntityFrameworkCore.SqlServer 7.0.3
- 目标框架:.NET 7.0
- 操作系统:Windows Server
问题分析与解决方案
核心原因
连接字符串中同时存在Trusted_Connection=true和user id/pwd参数时,SQL Server会优先采用Windows身份验证,直接忽略SQL Server身份验证的账号密码。此时应用程序会使用IIS应用程序池的身份连接数据库,默认池身份为Network Service,对应域账号就是{DOMAIN}\{MACHINE NAME}$,这就是错误日志中出现该账号的原因。
解决步骤
- 修改连接字符串:移除
Trusted_Connection=true参数,确保使用SQL Server身份验证:
"Database": "Server=data.example.com;Database=example_data;encrypt=no; user id=example; pwd=examplepassword;MultipleActiveResultSets=true"
或者将Trusted_Connection设置为false:
"Database": "Server=data.example.com;Database=example_data;Trusted_Connection=false;encrypt=no; user id=example; pwd=examplepassword;MultipleActiveResultSets=true"
验证数据库账号权限:确认
example账号拥有目标数据库example_data的访问权限,避免出现权限不足的后续错误。IIS应用程序池配置检查:如果后续需要切换为Windows身份验证,需将应用程序池的身份设置为具备数据库访问权限的域账号,同时连接字符串保留
Trusted_Connection=true并移除user id/pwd参数。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

