如何在IIS托管的ASP.Net Core应用中读取认证网络共享/UNC路径文件?
ASP.NET Core 读取Windows网络共享(UNC)文件的解决方案
问题描述
我有一个Windows FSX的UNC/网络共享,希望我的ASP.NET Core Web应用读取该共享中的文件。之前尝试使用SimpleImpersonation NuGet包,但该包已被弃用。请问在.NET Core中如何正确读取网络共享文件?以下是我之前的尝试代码:
var credentials = new UserCredentials(uncPath, userName, password); var result = WindowsIdentity.RunImpersonated(credentials, () => { return _fileSystem.File.ReadAllText($"\\\\{uncPath}\\test.txt"); });
可行解决方案
方法1:使用.NET内置身份模拟(WindowsIdentity.RunImpersonated)
SimpleImpersonation弃用后,可直接调用Windows API获取用户访问令牌,配合WindowsIdentity.RunImpersonated实现身份模拟。需引入System.Security.Principal和System.Runtime.InteropServices命名空间。
示例代码:
using System; using System.IO; using System.Runtime.InteropServices; using System.Security.Principal; public class NetworkFileReader { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); private const int LOGON32_LOGON_INTERACTIVE = 2; private const int LOGON32_PROVIDER_DEFAULT = 0; public string ReadNetworkFile(string uncPath, string domain, string username, string password) { if (!LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out IntPtr tokenHandle)) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } try { using var safeTokenHandle = new SafeAccessTokenHandle(tokenHandle); return WindowsIdentity.RunImpersonated(safeTokenHandle, () => { return File.ReadAllText(Path.Combine(uncPath, "test.txt")); }); } finally { CloseHandle(tokenHandle); } } }
注意:
- 本地账号传机器名作为
domain参数,域账号传域名 - 确保应用运行账号拥有调用
LogonUser的权限,可通过本地安全策略调整"允许本地登录"权限
方法2:配置应用池身份(IIS部署场景)
若为IIS部署的ASP.NET Core应用,可直接将应用池身份设为拥有网络共享访问权限的账号,无需手动模拟:
- 打开IIS管理器,找到目标应用池
- 右键选择"高级设置",修改"标识"为指定账号
- 确保该账号对目标网络共享拥有读取权限
- 直接通过UNC路径读取文件:
var content = File.ReadAllText(@"\\server\share\test.txt");
方法3:临时挂载网络共享(适合一次性操作)
通过命令行挂载网络共享为本地驱动器,读取后再卸载。注意此方法存在密码暴露风险,不推荐生产环境使用:
using System.Diagnostics; public string ReadFileViaMount(string uncPath, string driveLetter, string username, string password) { // 挂载共享 var processStartInfo = new ProcessStartInfo { FileName = "net", Arguments = $"use {driveLetter}: {uncPath} /user:{username} {password}", WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true }; using var process = Process.Start(processStartInfo); process.WaitForExit(); if (process.ExitCode != 0) { throw new InvalidOperationException("挂载网络共享失败"); } try { return File.ReadAllText($"{driveLetter}:\\test.txt"); } finally { // 卸载共享 var unmountProcess = Process.Start(new ProcessStartInfo { FileName = "net", Arguments = $"use {driveLetter}: /delete", WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true }); unmountProcess?.WaitForExit(); } }
常见注意事项
- 确保网络共享权限设置正确:目标账号需同时拥有共享文件夹和内部文件的读取权限
- Docker部署的Windows容器,需确保容器有权限访问主机或局域网的网络共享
- 避免硬编码账号密码,建议用配置文件或密钥管理服务存储敏感信息
内容的提问来源于stack exchange,提问作者CHash11
相关产品推荐
相关产品推荐

