How to provide user name and password when connecting to a network share

后端 未结 11 1676
不知归路
不知归路 2020-11-22 00:34

When connecting to a network share for which the current user (in my case, a network enabled service user) has no rights, name and password have to be provided.

I kn

11条回答
  •  有刺的猬
    2020-11-22 01:23

    The Luke Quinane solution looks good, but did work only partially in my ASP.NET MVC application. Having two shares on the same server with different credentials I could use the impersonation only for the first one.

    The problem with WNetAddConnection2 is also that it behaves differently on different windows versions. That is why I looked for alternatives and found the LogonUser function. Here is my code which also works in 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;
        }
    }
    

    Usage:

    var impersonationContext = new WrappedImpersonationContext(Domain, Username, Password);
    impersonationContext.Enter();
    
    //do your stuff here
    
    impersonationContext.Leave();
    

提交回复
热议问题