C#程序从网络目录运行时集成验证连SQL Server报错26 本地正常
以下C#代码实现SQL Server数据库查询功能时,程序从本地路径(如C:\myapp.exe)启动时运行完全正常,从网络驱动器(UNC路径\\filer,映射为Z盘)启动同一份程序时抛出SQL连接异常:
SqlConnectionStringBuilder sqlCSB = new SqlConnectionStringBuilder(); sqlCSB["Data Source"] = @"SERVER\MSSQL"; sqlCSB.Remove("User ID"); sqlCSB.Remove("Password"); sqlCSB["integrated Security"] = true; sqlCSB["Initial Catalog"] = "InitCatalog"; using (SqlConnection connection = new SqlConnection(sqlCSB.ConnectionString)) { using (SqlCommand cmd = connection.CreateCommand()) { cmd.CommandText = "SELECT * FROM public.v_Data;"; MessageBox.Show(System.Security.Principal.WindowsIdentity.GetCurrent().Name); // 无论从本地还是远程路径启动,此处弹窗均显示正确的一致账号 connection.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { int ord = reader.GetOrdinal("ColumnA"); while (reader.Read()) { returnedData.Add(reader.GetString(ord).Substring(2)); } } } } return returnedData;
抛出的异常信息如下:
System.Data.SqlClient.SqlException (0x80131904): (provider: SQL Network Interfaces, error: 26)
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Main.refresh() in Main.cs:Line 397. // 报错点为connection.Open();ClientConnectionId:00000000-0000-0000-0000-000000000000
(Error Number):-1,(State):0,(Class):20
已完成的前置验证:
- 无论本地还是网络路径启动,
WindowsIdentity.GetCurrent().Name返回的Windows账号完全一致 - 该账号本身拥有对应网络驱动器的访问权限
- 初步怀疑是Integrated Security集成安全认证机制与应用从网络目录启动的场景存在交互冲突
- .NET Framework默认安全区域限制:从UNC路径、映射网络驱动器加载的程序集会被自动归类到「本地Intranet」安全区域,默认不授予完全信任权限,缺少SqlClient发起SQL连接所需的凭据访问、网络通信权限,会直接导致实例解析、SSPI认证流程失败,触发error 26(SQL Server实例定位失败)错误。
- Windows网络文件标记限制:从网络位置启动的exe会被自动附加网络来源标记(存储在Zone.Identifier备用数据流中),这类进程调用SSPI做Windows集成认证时,系统LSASS服务默认不会向其发放可用于跨机器访问的网络认证凭据,仅能读取到当前账号的名称标识,无法完成对远程SQL Server的认证握手。
- 认知误区说明:
WindowsIdentity.GetCurrent().Name仅读取进程绑定的账号名称字符串,不会校验该安全上下文是否持有可用于跨网络认证的有效凭据,因此两种启动场景下显示账号一致,不能证明认证流程可正常执行。
- 基础网络连通性校验:在网络路径启动的程序中新增测试逻辑,分别验证SQL Server主机名解析、对应端口(默认实例1433,命名实例需查询对应动态端口)连通性、命名管道路径
\\SERVER\pipe\sql\query访问能力,先排除防火墙、网络策略的直接阻断。 - 解除文件网络锁定:右键点击网络共享中的exe文件,打开「属性」面板,如果底部安全提示栏存在「解除锁定」按钮,勾选后点击应用,清除文件的网络来源标记后重启程序测试。
- 配置远程加载程序集的完全信任权限:在exe同目录的配置文件(
你的程序名.exe.config)中添加如下配置,允许从网络位置加载的程序集以完全信任模式运行:
<configuration> <runtime> <loadFromRemoteSources enabled="true" /> </runtime> </configuration>
- 绕开实例解析流程测试:将连接字符串中的
Data Source改为SQL Server的固定IP+端口格式(例如10.0.0.20,1433),跳过SQL Browser服务的UDP 1434端口实例发现流程,如果修改后可正常连接,说明问题出在网络启动场景下程序无权限访问SQL Browser服务。 - 认证模式对比校验:临时将连接字符串改为SQL账号密码认证模式测试,如果SQL账号可正常连接,即可确认问题集中在Windows集成认证的权限限制上。此时可在Windows「Internet选项」-「安全」-「本地Intranet」-「站点」中,将程序所在的UNC共享路径添加到信任列表,调低该区域的安全级别,允许程序使用当前用户凭据发起网络认证。
内容的提问来源于stack exchange,提问作者BC5k4KwjAnebdrfD

