2009-02-24 23 views
8

私は、ネットワーク上の唯一のWindows 2003 Serverに接続すると、次のエラーが生成さNovellネットワーク上で実行されているWinFormsのクライアントサーバーアプリケーションを持っている:DirectoryInfo.GetFilesがこのIOExceptionを生成する理由を説明できますか?

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の接続を管理しますワークステーションのユーザー名とパスワードをサーバー上のローカルユーザーと同期させます。エラーの奇妙な点は、ユーザーが明示的にログオンせずにエラーの前後にサーバーに書き込むことができることです。

なぜエラーが発生したのか解説できますか?

+0

NovellとWindowsワークグループまたはドメインとの間に暗黙的な信頼関係がないことがあります。 –

+0

この「暗黙の信頼」は構成可能なものですか? – flipdoubt

+0

サーバーに接続するコードセグメントを投稿できますか? – AviD

答えて

38

別のドメインの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. 
} 
+0

私は同様の方法でユーザーを偽装していますが、ユーザーがローカル管理者である場合にのみ機能するようです。これが事実だと分かりますか? – flipdoubt

+0

どのユーザーがローカル管理者である必要がありますか?共有にアクセスするには、リモートユーザーが管理者である必要があります。 – David

+0

私は、ローカルコンピュータ上で何らかの "偽装できるユーザー"権限を必要としていると言いますが、ほとんどの標準ユーザーはそうしていません。 – flipdoubt

1

私は、問題を再現して、ネットワークトラフィックを確認し、障害の状況と成功状況の違いを見るためにパケットモニタを使用するようにしてください。

次に、Windows(P/Invokes)からraw APIを使用してアプリケーションを作成して、障害の状況を再現し、エラーを引き起こすパラメータを見つけようとします。問題を解決できるのであれば、必要なことを行うためにコンポーネントを取得する方法を見つけることの問題です。あなたが見て可能性が

他の方向(あなたは安定して問題を再現することができた後):

  • すべてのAPI呼び出しを記録し、エラーがどこから来るか見るためにProcess Monitorを使用してください。
  • は、ウイルススキャナ
  • 更新
1

は私見、さわやかの副作用のいくつかの種類であるように思わノベルクライアントを無効にきれいなVM /マシン上でそれを試してみて、そこにそれを再現しよう期限切れの認証トークン(またはそのようなもの)

私のケースでは、プロキシ(squid)経由のインターネットアクセスを持つユーザーとして、ページの更新によって解決される資格情報の不足に関するエラーを(ランダムな間隔で)取得するまでは問題なくブラウジングしていますブラウザでは、次のエラーまですべてが正常に動作しています。

2

VB.Net開発者(私のような)には、VBがあります。Netバージョン:

Imports System 
Imports System.ComponentModel 
Imports System.Runtime.InteropServices 
Imports System.Security.Principal 

Namespace Company.Security 
    Public Class ImpersonateUser 
     Implements IDisposable 

     <DllImport("advapi32.dll", SetLastError:=True)> _ 
     Private Shared Function LogonUser(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer 
     End Function 

     <DllImport("kernel32", SetLastError:=True)> _ 
     Private Shared Function CloseHandle(ByVal hObject As IntPtr) As Boolean 
     End Function 

     Private userHandle As IntPtr = IntPtr.Zero 
     Private impersonationContext As WindowsImpersonationContext 

     Public Sub New(ByVal user As String, ByVal domain As String, ByVal password As String) 
      If Not String.IsNullOrEmpty(user) Then 
       Dim loggedOn As Integer = LogonUser(user, domain, password, 9, 3, userHandle) 
       If Not loggedOn = 1 Then 
        Throw New Win32Exception(Marshal.GetLastWin32Error()) 
       End If 
       impersonationContext = WindowsIdentity.Impersonate(userHandle) 
      End If 
     End Sub 

     Public Sub Dispose() Implements System.IDisposable.Dispose 
      If userHandle <> IntPtr.Zero Then 
       CloseHandle(userHandle) 
      End If 
      If impersonationContext IsNot Nothing Then 
       impersonationContext.Undo() 
      End If 
     End Sub 

    End Class 
End Namespace 

など、それを使用します。

using New ImpersonateUser("UserID", "Domain", "Password") 
    ' ... your code here 
End Using 
0

あり、Microsoftの例では、このアドレスで利用可能です:https://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext(v=vs.110).aspx

しかし、それは彼らの例で言うん:「Windows Vistaでは、および後でこのサンプルを管理者として実行する必要があります。

このソリューションは、コードを実行しているユーザーがほとんどのプラットフォームで管理者である場合にのみ有効です。

関連する問題