在 C# 中使用身份验证复制文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17786037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
copy files with authentication in c#
提问by user1065542
I am trying to copy file from local drive to one of folder on server. name of the folder on server is 'DBFiles'. No one has got access to this apart from username 'user' and password 'password1!'
我正在尝试将文件从本地驱动器复制到服务器上的文件夹之一。服务器上文件夹的名称是“DBFiles”。除了用户名“user”和密码“password1!”之外,没有人可以访问它。
before coping the file, it creates the directory if not exisits as well.
在处理文件之前,它会创建目录(如果不存在)。
can someone help to get access while creating directory 'Test' and then copy a files.
有人可以在创建目录“Test”时帮助获得访问权限,然后复制文件。
if (!Directory.Exists(@"\server-a\copiedfiles\"))
Directory.CreateDirectory(@"\server-a\DBFiles\"+Test);
File.Copy("C:\Temp\abc.txt", @"\server-a\DBFiles\");
This is the original code in c#.
这是c#中的原始代码。
NetworkShare.DisconnectFromShare(@"\server-a\DBFiles", true); //Disconnect in case we are currently connected with our credentials;
NetworkShare.ConnectToShare(@"\server-a\DBFiles", "user1", "password1!"); //Connect with the new credentials
File.Copy(@"c:\temp\T1.txt", @"\server-a\DBFiles\T1.txt");
NetworkShare.DisconnectFromShare(@"\server-a\DBFiles", false); //Disconnect from the server.
Its giving error as Access Denied.
它给出的错误是访问被拒绝。
回答by Peter
You can use impersonation to change the threads user context:
您可以使用模拟来更改线程用户上下文:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
...
LogonUser(userName, domainName, password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
...
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
{
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
// Check the identity.
Console.WriteLine("After impersonation: "
+ WindowsIdentity.GetCurrent().Name);
//Do your coping here
}
}
回答by Scott Chamberlain
Another option is you can programmaticly access the NET USE
api of windows and authenticate to the share like if you went to it in explorer and typed in the credientals.
另一种选择是您可以以编程方式访问NET USE
Windows的api 并验证共享,就像您在资源管理器中访问它并输入凭据一样。
public static class NetworkShare
{
/// <summary>
/// Connects to the remote share
/// </summary>
/// <returns>Null if successful, otherwise error message.</returns>
public static string ConnectToShare(string uri, string username, string password)
{
//Create netresource and point it at the share
NETRESOURCE nr = new NETRESOURCE();
nr.dwType = RESOURCETYPE_DISK;
nr.lpRemoteName = uri;
//Create the share
int ret = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);
//Check for errors
if (ret == NO_ERROR)
return null;
else
return GetError(ret);
}
/// <summary>
/// Remove the share from cache.
/// </summary>
/// <returns>Null if successful, otherwise error message.</returns>
public static string DisconnectFromShare(string uri, bool force)
{
//remove the share
int ret = WNetCancelConnection(uri, force);
//Check for errors
if (ret == NO_ERROR)
return null;
else
return GetError(ret);
}
#region P/Invoke Stuff
[DllImport("Mpr.dll")]
private static extern int WNetUseConnection(
IntPtr hwndOwner,
NETRESOURCE lpNetResource,
string lpPassword,
string lpUserID,
int dwFlags,
string lpAccessName,
string lpBufferSize,
string lpResult
);
[DllImport("Mpr.dll")]
private static extern int WNetCancelConnection(
string lpName,
bool fForce
);
[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public int dwScope = 0;
public int dwType = 0;
public int dwDisplayType = 0;
public int dwUsage = 0;
public string lpLocalName = "";
public string lpRemoteName = "";
public string lpComment = "";
public string lpProvider = "";
}
#region Consts
const int RESOURCETYPE_DISK = 0x00000001;
const int CONNECT_UPDATE_PROFILE = 0x00000001;
#endregion
#region Errors
const int NO_ERROR = 0;
const int ERROR_ACCESS_DENIED = 5;
const int ERROR_ALREADY_ASSIGNED = 85;
const int ERROR_BAD_DEVICE = 1200;
const int ERROR_BAD_NET_NAME = 67;
const int ERROR_BAD_PROVIDER = 1204;
const int ERROR_CANCELLED = 1223;
const int ERROR_EXTENDED_ERROR = 1208;
const int ERROR_INVALID_ADDRESS = 487;
const int ERROR_INVALID_PARAMETER = 87;
const int ERROR_INVALID_PASSWORD = 1216;
const int ERROR_MORE_DATA = 234;
const int ERROR_NO_MORE_ITEMS = 259;
const int ERROR_NO_NET_OR_BAD_PATH = 1203;
const int ERROR_NO_NETWORK = 1222;
const int ERROR_SESSION_CREDENTIAL_CONFLICT = 1219;
const int ERROR_BAD_PROFILE = 1206;
const int ERROR_CANNOT_OPEN_PROFILE = 1205;
const int ERROR_DEVICE_IN_USE = 2404;
const int ERROR_NOT_CONNECTED = 2250;
const int ERROR_OPEN_FILES = 2401;
private struct ErrorClass
{
public int num;
public string message;
public ErrorClass(int num, string message)
{
this.num = num;
this.message = message;
}
}
private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"),
new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"),
new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"),
new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"),
new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"),
new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"),
new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"),
new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"),
new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"),
new ErrorClass(ERROR_MORE_DATA, "Error: More Data"),
new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"),
new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"),
new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"),
new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"),
new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"),
new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"),
new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"),
new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"),
new ErrorClass(ERROR_SESSION_CREDENTIAL_CONFLICT, "Error: Credential Conflict"),
};
private static string GetError(int errNum)
{
foreach (ErrorClass er in ERROR_LIST)
{
if (er.num == errNum) return er.message;
}
return "Error: Unknown, " + errNum;
}
#endregion
#endregion
}
You use it simply like
你使用它就像
DisconnectFromShare(@"\server-a\DBFiles", true); //Disconnect in case we are currently connected with our credentials;
ConnectToShare(@"\server-a\DBFiles", username, password); //Connect with the new credentials
if (!Directory.Exists(@"\server-a\DBFiles\"))
Directory.CreateDirectory(@"\server-a\DBFiles\"+Test);
File.Copy("C:\Temp\abc.txt", @"\server-a\DBFiles\");
DisconnectFromShare(@"\server-a\DBFiles", false); //Disconnect from the server.
回答by Nayoon Cooray
NetworkShare.DisconnectFromShare(@"\server-a\DBFiles", true); //Remove this line
NetworkShare.ConnectToShare(@"\server-a\DBFiles", "user1", "password1!"); //Connect with the new credentials
File.Copy(@"c:\temp\T1.txt", @"\server-a\DBFiles\T1.txt");
NetworkShare.DisconnectFromShare(@"\server-a\DBFiles", false); //Remove this line also
After 02 days search in Google finally the above worked for me.
If you use 'NetworkShare.DisconnectFromShare
' after the first login you will get an error as 'Access denied'
. Then every time you need to restart the server or need to execute 'net use * /del'
command to delete the saved credentials in windows.
在谷歌搜索 02 天后,上述内容终于对我有用。如果您NetworkShare.DisconnectFromShare
在第一次登录后使用 ' ',您将收到错误消息'Access denied'
。然后每次您需要重新启动服务器或需要执行'net use * /del'
命令以删除 Windows 中保存的凭据时。
回答by Sapnandu
I have done this file copy from remote server. please find the code.
我已经从远程服务器复制了这个文件。请找到代码。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.Security.Principal;
using System.Runtime.InteropServices;
namespace IMPolicy
{
public partial class ExtractData : System.Web.UI.Page
{
[DllImport("advapi32.DLL", SetLastError = true)]
public static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
protected void Page_Load(object sender, EventArgs e)
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
IntPtr token = default(IntPtr);
if (LogonUser("UserName", "Domain", "Password", 2, 0, ref token) != 0)
{
WindowsIdentity identity = new WindowsIdentity(token);
WindowsImpersonationContext context = identity.Impersonate();
try
{
File.Copy(@"\\10.10.38.25\d$\Sourav\Draft Report ITC-LRBD_Online Booking Portal_12082016.pdf", @"d:\Draft Report ITC-LRBD_Online Booking Portal_12082016.pdf", true);
}
finally
{
context.Undo();
}
}
}
}
}