我有一个在Novell网络上运行的WinForms客户端 - 服务器应用程序,当连接到网络上的单独Windows 2003 Server时会产生以下错误:
TYPE: System.IO.IOException MSG: Logon failure: unknown user name or bad password. SOURCE: mscorlib SITE: WinIOError at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.Directory.InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption) at System.IO.DirectoryInfo.GetFiles(String searchPattern, SearchOption searchOption) at System.IO.DirectoryInfo.GetFiles(String searchPattern) at Ceoimage.Basecamp.DocumentServers.ClientAccessServer.SendQueuedFiles( Int32 queueId, Int32 userId, IDocQueueFile[] queueFiles) at Ceoimage.Basecamp.ScanDocuments.DataModule.CommitDocumentToQueue( QueuedDocumentModelWithCollections doc, IDocQueueFile[] files)
客户的网络管理员通过手动将工作站用户名和密码与服务器上的本地用户同步来管理Windows Server连接.关于错误的奇怪之处在于用户可以在错误之前和之后写入服务器,所有这些都没有明确登录.
你能解释一下错误发生的原因并提供解决方案吗?
尝试访问其他域中的Windows服务器的文件系统时,我遇到同样的问题.问题是程序运行的用户帐户无法访问远程服务器.Windows在幕后进行额外的工作,使其在使用Windows资源管理器时看起来无缝,因为它猜测您的远程凭据将与您的本地凭据匹配.
如果您将驱动器本地映射到远程服务器,然后在代码中使用本地映射的驱动器,您应该没有问题.如果您无法映射驱动器,但可以硬编码用于远程服务器的凭据,则可以使用以下代码:
using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Security.Principal; namespace Company.Security { public class ImpersonateUser : IDisposable { [DllImport("advapi32.dll", SetLastError=true)] private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport( "kernel32", SetLastError = true )] private static extern bool CloseHandle(IntPtr hObject); private IntPtr userHandle = IntPtr.Zero; private WindowsImpersonationContext impersonationContext; public ImpersonateUser( string user, string domain, string password ) { if ( ! string.IsNullOrEmpty( user ) ) { // Call LogonUser to get a token for the user bool loggedOn = LogonUser( user, domain, password, 9 /*(int)LogonType.LOGON32_LOGON_NEW_CREDENTIALS*/, 3 /*(int)LogonProvider.LOGON32_PROVIDER_WINNT50*/, out userHandle ); if ( !loggedOn ) throw new Win32Exception( Marshal.GetLastWin32Error() ); // Begin impersonating the user impersonationContext = WindowsIdentity.Impersonate( userHandle ); } } public void Dispose() { if ( userHandle != IntPtr.Zero ) CloseHandle( userHandle ); if ( impersonationContext != null ) impersonationContext.Undo(); } } }
然后,您可以通过执行以下操作访问远程服务器:
using ( new ImpersonateUser( "UserID", "Domain", "Password" ) ) { // Any IO code within this block will be able to access the remote server. }