如何在C#中利用Windows已保存凭据访问局域网共享文件夹
如何在C#中利用Windows暂存凭据访问局域网共享文件夹?
问题描述
我正在开发一款需要访问局域网共享文件夹、进行文件读取与修改操作的应用,但不想要求用户输入凭据。若用户此前已使用凭据访问过该共享文件夹,能否借助Windows的凭据暂存功能(重启前有效)?是否可通过C#“获取”/使用这些凭据或“配置文件”来访问共享位置?
我当前的实现方式是请求用户提供凭据后进行模拟登录,但希望能避免这种方式:
token = IntPtr.Zero; var success = LogonUser(machine_username, remote_machine, machine_password, 9, 0, ref token); using (WindowsImpersonationContext person = new WindowsIdentity(token).Impersonate()) { try { // do something on the network location } catch (IOException) { Console.WriteLine("Connection with the server failed!"); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { person.Undo(); CloseHandle(token); } }
解决方案
当然可以!Windows会自动暂存用户最近访问共享资源时输入的凭据(重启前有效),只要你的应用运行在当前用户的登录会话中,就能直接利用这个缓存来访问共享,完全不需要手动获取或存储凭据。
1. 核心思路:利用Windows网络连接API自动复用凭据
不需要使用LogonUser做用户模拟,而是调用Windows原生的WNetAddConnection2 API——这个API会自动尝试使用当前用户凭据缓存中的信息来建立共享连接,无需手动传入用户名和密码。
2. C#实现代码示例
首先需要引入API的DllImport声明,然后调用它来建立共享连接:
using System; using System.Runtime.InteropServices; public class NetworkShareHelper { // 定义WNetAddConnection2需要的结构体 [StructLayout(LayoutKind.Sequential)] private struct NETRESOURCE { public int dwScope; public int dwType; public int dwDisplayType; public int dwUsage; public string lpLocalName; public string lpRemoteName; public string lpComment; public string lpProvider; } // 导入WNetAddConnection2 API [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern int WNetAddConnection2(ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags); // 导入WNetCancelConnection2 API用于断开连接(可选) [DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern int WNetCancelConnection2(string lpName, int dwFlags, bool fForce); public static bool ConnectToShare(string sharePath) { NETRESOURCE resource = new NETRESOURCE { dwType = 0x00000001, // 资源类型为磁盘 lpRemoteName = sharePath }; // 调用API,用户名和密码传null,自动使用缓存凭据 int result = WNetAddConnection2(ref resource, null, null, 0); return result == 0; // 返回0表示成功 } public static bool DisconnectFromShare(string sharePath) { int result = WNetCancelConnection2(sharePath, 0, true); return result == 0; } } // 使用示例 public class Program { public static void Main() { string sharePath = @"\\servername\sharedfolder"; if (NetworkShareHelper.ConnectToShare(sharePath)) { try { // 在这里执行文件读取/修改操作,比如: string[] files = System.IO.Directory.GetFiles(sharePath); foreach (var file in files) { Console.WriteLine(file); } } catch (Exception ex) { Console.WriteLine($"操作失败:{ex.Message}"); } finally { NetworkShareHelper.DisconnectFromShare(sharePath); } } else { Console.WriteLine("无法连接到共享文件夹,请检查是否已访问过该共享或凭据是否有效。"); } } }
3. 关键注意事项
- 会话一致性:确保你的应用是在用户登录的交互式会话中运行,不要以服务身份运行——服务通常运行在独立的会话,无法访问当前用户的凭据缓存。
- 降级处理:如果凭据缓存中没有对应共享的凭据,
WNetAddConnection2会返回错误,这时你可以选择提示用户输入凭据(作为降级方案),但大部分场景下,用户之前访问过的话就能直接复用缓存。 - 权限问题:应用运行的用户需要有访问该共享文件夹的权限,缓存的凭据也必须对应有权限的账户。
内容的提问来源于stack exchange,提问作者CameFromSpace
相关产品推荐
相关产品推荐

