我们遇到了一个需要解决的有趣情况,我的搜索已经发现了 . 因此,我呼吁SO社区寻求帮助 .
问题是:我们需要以编程方式访问不在我们域中的共享文件,并且不在远程文件共享/ UNC的可信外部域中 . 当然,我们需要为远程计算机提供凭据 .
通常,可以通过以下两种方式之一解决此问题:
-
将文件共享映射为驱动器并在此时提供凭据 . 这通常使用
NET USE
命令或复制NET USE
的Win32函数来完成 . -
使用UNC路径访问文件,就好像远程计算机位于域上一样,并确保作为本地用户在远程计算机上复制运行程序的帐户(包括密码) . 基本上利用了当用户尝试访问共享文件时Windows将自动提供当前用户凭据的事实 .
-
不要使用远程文件共享 . 使用FTP(或其他方法)传输文件,在本地处理它,然后将其传回 .
出于各种各样的原因,我们的安全/网络架构师拒绝了前两种方法 . 第二种方法显然是一个安全漏洞;如果远程计算机受到危害,则本地计算机现在处于危险之中 . 第一种方法是不能令人满意的,因为新安装的驱动器是在程序访问文件期间本地计算机上的其他程序可用的共享资源 . 尽管这很可能使这个暂时存在,但他们认为这仍然是一个漏洞 .
他们对第三种选择持开放态度,但远程网络管理员坚持使用SFTP而不是FTPS,而FtpWebRequest仅支持FTPS . SFTP is 更适合防火墙的选项,我可以使用几个库来实现这种方法,但如果可以的话,我宁愿减少我的依赖项 .
我在MSDN上搜索了使用远程文件共享的托管或win32方法,但我没有提出任何有用的东西 .
所以我问:还有另外一种方法吗?我是否错过了一个超级秘密的win32功能,可以满足我的需求?或者我必须追求选项3的一些变体?
9 回答
对于寻求快速解决方案的人来说,你可以使用我最近写的
NetworkShareAccesser
(基于this answer(非常感谢!)):Usage:
WARNING: 请确保
Dispose
的Dispose
被调用(即使你的应用程序崩溃了!),否则Windows上将保留打开的连接 . 您可以通过打开cmd
提示并输入net use
来查看所有打开的连接 .The Code:
解决问题的方法是使用名为WNetUseConnection的Win32 API .
Use this function to connect to a UNC path with authentication, NOT to map a drive .
这将允许您连接到远程计算机,即使它不在同一个域上,即使它具有不同的用户名和密码 .
使用WNetUseConnection后,您将能够通过UNC路径访问该文件,就像您在同一个域中一样 . 最好的方法可能是通过行政内置股票 .
示例:\ computername \ c $ \ program files \ Folder \ file.txt
Here is some sample C# code that uses WNetUseConnection .
注意,对于NetResource,您应该为lpLocalName和lpProvider传递null . dwType应为RESOURCETYPE_DISK . lpRemoteName应为\ ComputerName .
我已经看到选项3以JScape tools以非常简单的方式实现了 . 你可以尝试一下 . 它不是免费的,但它确实起作用 .
而不是WNetUseConnection,我会推荐NetUseAdd . WNetUseConnection是一个遗留功能,在Windows资源管理器中可见_303972 . NetUseAdd相当于在DOS提示符下调用net use以在远程计算机上进行身份验证 .
如果您调用NetUseAdd,则后续尝试访问该目录应该会成功 .
大多数SFTP服务器也支持SCP,这可以更容易地找到库 . 您甚至可以从代码中调用现有客户端,例如PuTTY中包含的pscp .
如果您正在使用的文件类型简单,如文本或XML文件,您甚至可以编写自己的客户端/服务器实现来使用.NET Remoting或Web服务等操作文件 .
我找了MS找到答案 . 第一种解决方案假定运行应用程序进程的用户帐户可以访问共享文件夹或驱动器(同一域) . 确保您的DNS已解析或尝试使用IP地址 . 只需执行以下操作:
如果您想跨越不同的域,带有凭据的.NET 2.0遵循以下模型:
AFAIK,您不需要_C3962_为驱动器号的UNC路径,以便为服务器 Build 凭据 . 我经常使用批处理脚本,如:
但是,与您的程序在同一帐户上运行的任何程序仍然可以访问
username:password
具有的所有内容进入 . 一种可能的解决方案是将您的程序隔离在自己的本地用户帐户中(UNC访问权限是名为NET USE
的帐户的本地访问) .Note: 使用SMB跨域并不是很好地利用IMO这项技术 . 如果安全性非常重要,那么SMB缺乏加密这一事实本身就是一种阻碍 .
虽然我不了解自己,但我当然希望#2不正确......我想我认为Windows不会自动将我的登录信息(至少我的密码!)发给任何一台机器,更不用说不属于我信任的一个 .
无论如何,你有没有探索过模仿架构?您的代码看起来与此类似:
在这种情况下,
token
变量是IntPtr . 为了获得此变量的值,您必须调用非托管的LogonUser Windows API函数 . 快速前往pinvoke.net给我们以下签名:用户名,域名和密码应该看起来相当明显 . 查看可以传递给dwLogonType和dwLogonProvider的各种值,以确定最适合您需求的值 .
此代码尚未经过测试,因为我在此处没有第二个域可以验证,但这应该会让您走上正确的轨道 .
这里有一个最小的POC类w /所有被删除的
你可以直接使用
\\server\share\folder
w /WNetUseConnection
,不需要事先将它剥离到\\server
部分 .