6

C# 内では、次のことができる必要があります。

  • 必要に応じてユーザー名/パスワードを指定して、リモート システムに接続します
  • そのシステムのローカル グループのメンバーを一覧表示する
  • 結果を実行中のコンピューターにフェッチします

したがって、たとえば、適切な資格情報を使用して \SOMESYSTEM に接続し、SOMESYSTEM\Administrator、SOMESYSTEM\Bob、DOMAIN\AlanH、「DOMAIN\Domain Administrators」を含むローカル管理者のリストを取得します。

system.directoryservices.accountmanagement でこれを試しましたが、認証で問題が発生しています。時々私は得る:

複数のユーザー名を使用して、同じユーザーがサーバーまたは共有リソースに複数接続することは許可されていません。サーバーまたは共有リソースへの以前の接続をすべて切断して、再試行してください。(HRESULT からの例外: 0x800704C3)

既存のドライブまたは UNC 接続を単純にマップ解除できない状況があるため、上記は試しています。

また、プログラムが UNKNOWN ERROR を取得し、リモート システムのセキュリティ ログがエラー 675、コード 0x19 (KDC_ERR_PREAUTH_REQUIRED) を報告することもあります。

これを行うには、より簡単でエラーが発生しにくい方法が必要です!

4

5 に答える 5

2

davidg は正しい方向に進んでおり、私は彼の答えを信じています。

しかし、必要な WMI クエリは単純ではありませんでした。マシン全体のユーザーのリストだけでなく、ローカルかドメインかに関係なく、ローカルの Administrators グループのメンバーであるユーザーとグループのサブセットが必要だったからです。記録として、その WMI クエリは次のとおりです。

SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain='thehostname',Name='thegroupname'"

完全なコード スニペットは次のとおりです。

public string GroupMembers(string targethost, string groupname, string targetusername, string targetpassword)
        {
            StringBuilder result = new StringBuilder(); 
            try
            {
                ConnectionOptions Conn = new ConnectionOptions();
                if (targethost != Environment.MachineName) //WMI errors if creds given for localhost
                {
                    Conn.Username = targetusername; //can be null
                    Conn.Password = targetpassword; //can be null
                }
                Conn.Timeout = TimeSpan.FromSeconds(2);
                ManagementScope scope = new ManagementScope("\\\\" + targethost + "\\root\\cimv2", Conn);
                scope.Connect();
                StringBuilder qs = new StringBuilder();
                qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='");
                qs.Append(targethost);
                qs.Append("',Name='");
                qs.Append(groupname);
                qs.AppendLine("'\"");
                ObjectQuery query = new ObjectQuery(qs.ToString());
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection queryCollection = searcher.Get();
                foreach (ManagementObject m in queryCollection)
                {
                    ManagementPath path = new ManagementPath(m["PartComponent"].ToString());                                        
                    { 
                        String[] names = path.RelativePath.Split(',');
                        result.Append(names[0].Substring(names[0].IndexOf("=") + 1).Replace("\"", " ").Trim() + "\\"); 
                        result.AppendLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace("\"", " ").Trim());                    
                    }
                }
                return result.ToString();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error. Message: " + e.Message);
                return "fail";
            }
        }

したがって、Groupmembers("Server1", "Administrators", "myusername", "mypassword"); を呼び出すと、次のように単一の文字列が返されます。

SERVER1\Administrator
MYDOMAIN\Domain Admins

実際の WMI の戻り値は次のようになります。

\\SERVER1\root\cimv2:Win32_UserAccount.Domain="SERVER1",Name="管理者"

...ご覧のとおり、文字列を少し操作してきれいにする必要がありました。

于 2008-08-23T08:14:15.430 に答える
1

これは、WMI を使用して簡単に実行できます。ここにいくつかのドキュメントへのポインタがあります:

Win32_UserAccount の WMI ドキュメント

WMI の経験がない場合でも、ページの下部にある VB スクリプト コードを .NET コードに変換するのは非常に簡単です。

これが役に立ったことを願っています!

于 2008-08-22T00:57:21.463 に答える
1

Win32 API 関数NetLocalGroupGetMembersを使用することをお勧めします。ここで推奨されている他のソリューションのいくつかに必要なクレイジーな LDAP 構文を理解しようとするよりも、はるかに簡単です。「LoginUser」を呼び出して、チェックを実行したいユーザーになりすます限り、セキュリティ上の問題は発生しません。

なりすましを行うためのサンプル コードは、こちらにあります

C# から "NetLocalGroupGetMembers" を呼び出す方法を理解するのに助けが必要な場合は、 codeplex からダウンロードできる Jared Parson の PInvoke アシスタントを確認することをお勧めします。

IIS で実行されている ASP.NET アプリでコードを実行していて、呼び出しを行うために Web サイトにアクセスしているユーザーを偽装する場合は、運用 Web サーバーに "Trusted for Delegation" アクセス許可を付与する必要がある場合があります。

デスクトップで実行している場合は、アクティブなユーザーのセキュリティ資格情報を使用しても問題ありません。

ネットワーク管理者が、アクセスしようとしている特定のマシンの「保護可能なオブジェクト」へのアクセスを取り消した可能性があります。残念ながら、すべてのネットワーク管理 API機能が機能するには、そのアクセスが必要です。その場合は、実行するユーザーに「保護可能なオブジェクト」へのアクセスを許可する必要があります。ただし、デフォルトの Windows セキュリティ設定では、認証されたすべてのユーザーがアクセスできるはずです。

これが役立つことを願っています。

-スコット

于 2008-08-22T01:36:33.757 に答える
0

System.DirectoryServices.DirectoryEntry でこれを行うことができるはずです。リモートでの実行に問題がある場合は、リモート マシンに何かをインストールして、リモート処理や Web サービスなど、ある種の RPC 経由でデータを提供することができます。しかし、あなたがしようとしていることは、あまりにも派手になることなくリモートで可能であるべきだと思います.

于 2008-08-22T00:43:13.823 に答える
0

Windowsがログインメカニズムを介して接続できない場合、唯一のオプションは、開いているポートを使用してリモートマシンで何かを実行することだと思います(前述のように、直接またはリモートまたはWebサービスを介して)。

于 2008-08-22T00:55:35.557 に答える