当连接到当前用户(在我的例子中,是启用网络的服务用户)没有权限的网络共享时,必须提供名称和密码。
我知道如何用Win32函数(来自mpr.dll的WNet*家族)做到这一点,但想用. net(2.0)功能。
有哪些选择?
也许更多的信息会有所帮助:
用例是一个windows服务,而不是一个Asp。网络应用程序。 该服务运行在一个没有共享权限的帐户下。 客户端不知道共享所需的用户帐户。 客户端和服务器不是同一域的成员。
当连接到当前用户(在我的例子中,是启用网络的服务用户)没有权限的网络共享时,必须提供名称和密码。
我知道如何用Win32函数(来自mpr.dll的WNet*家族)做到这一点,但想用. net(2.0)功能。
有哪些选择?
也许更多的信息会有所帮助:
用例是一个windows服务,而不是一个Asp。网络应用程序。 该服务运行在一个没有共享权限的帐户下。 客户端不知道共享所需的用户帐户。 客户端和服务器不是同一域的成员。
当前回答
你应该像这样添加一行:
<identity impersonate="true" userName="domain\user" password="****" />
在你的web.config中。
更多的信息。
其他回答
你应该像这样添加一行:
<identity impersonate="true" userName="domain\user" password="****" />
在你的web.config中。
更多的信息。
我找了很多方法,我按自己的方式做了。您必须通过命令提示符NET USE命令打开两台机器之间的连接,并在完成工作后使用命令提示符NET USE "myconnection" /delete清除连接。
你必须使用命令提示符处理后面的代码,像这样:
var savePath = @"\\servername\foldername\myfilename.jpg";
var filePath = @"C:\\temp\myfileTosave.jpg";
用法很简单:
SaveACopyfileToServer(filePath, savePath);
函数如下:
using System.IO
using System.Diagnostics;
public static void SaveACopyfileToServer(string filePath, string savePath)
{
var directory = Path.GetDirectoryName(savePath).Trim();
var username = "loginusername";
var password = "loginpassword";
var filenameToSave = Path.GetFileName(savePath);
if (!directory.EndsWith("\\"))
filenameToSave = "\\" + filenameToSave;
var command = "NET USE " + directory + " /delete";
ExecuteCommand(command, 5000);
command = "NET USE " + directory + " /user:" + username + " " + password;
ExecuteCommand(command, 5000);
command = " copy \"" + filePath + "\" \"" + directory + filenameToSave + "\"";
ExecuteCommand(command, 5000);
command = "NET USE " + directory + " /delete";
ExecuteCommand(command, 5000);
}
ExecuteCommand函数为:
public static int ExecuteCommand(string command, int timeout)
{
var processInfo = new ProcessStartInfo("cmd.exe", "/C " + command)
{
CreateNoWindow = true,
UseShellExecute = false,
WorkingDirectory = "C:\\",
};
var process = Process.Start(processInfo);
process.WaitForExit(timeout);
var exitCode = process.ExitCode;
process.Close();
return exitCode;
}
这个函数对我来说非常快速和稳定。
这肯定是最愚蠢的方法,但它最近对我很有用,而且它简单得可笑。 当然,只能在Windows上使用。
Process.Start("CMDKEY", @"/add:""NetworkName"" /user:""Username"" /pass:""Password""");
然后,在尝试访问共享之前,可能需要使用WaitForExit()。
您可以在最后删除凭证,再次使用CMDKEY命令。
一种可行的方法是使用WindowsIdentity。模拟(并更改线程主体)成为所需的用户,如下所示。回到p/invoke,不过,恐怕……
另一个厚脸皮的(同样不理想的)选择可能是生成一个流程来完成这项工作……ProcessStartInfo接受. username, . password和. domain。
最后-也许在一个有权限的专用帐户中运行服务?(删除,因为你已经澄清这不是一个选项)。
卢克奎宁的解决方案看起来不错,但只部分工作在我的ASP。NET MVC应用程序。在同一服务器上使用不同凭证的两个共享,我只能对第一个使用模拟。
WNetAddConnection2的问题还在于它在不同的windows版本上表现不同。这就是为什么我寻找替代品,并找到了LogonUser功能。这是我的代码,也工作在ASP。NET:
public sealed class WrappedImpersonationContext
{
public enum LogonType : int
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
Unlock = 7,
NetworkClearText = 8,
NewCredentials = 9
}
public enum LogonProvider : int
{
Default = 0, // LOGON32_PROVIDER_DEFAULT
WinNT35 = 1,
WinNT40 = 2, // Use the NTLM logon provider.
WinNT50 = 3 // Use the negotiate logon provider.
}
[DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain,
String lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll")]
public extern static bool CloseHandle(IntPtr handle);
private string _domain, _password, _username;
private IntPtr _token;
private WindowsImpersonationContext _context;
private bool IsInContext
{
get { return _context != null; }
}
public WrappedImpersonationContext(string domain, string username, string password)
{
_domain = String.IsNullOrEmpty(domain) ? "." : domain;
_username = username;
_password = password;
}
// Changes the Windows identity of this thread. Make sure to always call Leave() at the end.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Enter()
{
if (IsInContext)
return;
_token = IntPtr.Zero;
bool logonSuccessfull = LogonUser(_username, _domain, _password, LogonType.NewCredentials, LogonProvider.WinNT50, ref _token);
if (!logonSuccessfull)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
WindowsIdentity identity = new WindowsIdentity(_token);
_context = identity.Impersonate();
Debug.WriteLine(WindowsIdentity.GetCurrent().Name);
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Leave()
{
if (!IsInContext)
return;
_context.Undo();
if (_token != IntPtr.Zero)
{
CloseHandle(_token);
}
_context = null;
}
}
用法:
var impersonationContext = new WrappedImpersonationContext(Domain, Username, Password);
impersonationContext.Enter();
//do your stuff here
impersonationContext.Leave();