在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:28:06  来源:igfitidea点击:

copy files with authentication in c#

c#.net

提问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
                }
            }

MSDN Sample windowsimpersonationcontext

MSDN 示例窗口模拟上下文

回答by Scott Chamberlain

Another option is you can programmaticly access the NET USEapi of windows and authenticate to the share like if you went to it in explorer and typed in the credientals.

另一种选择是您可以以编程方式访问NET USEWindows的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();
             }
        }




    }


  }
}