あなたの問題は明らかです。現在の実装では、ユーザーの偽装のみがあり、委任はありません。Stephen Martin によって既に書かれた情報を繰り返したくありません。少なくとも 3 つのソリューションを追加したいだけです。Stephen Martin が提案する委任の古典的な方法は、1 つの方法にすぎません。ここでいくつかの方法を読むことができます: http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_delegation。問題を解決するための 3 つの実用的な方法があります。
ユーザーの偽装トークンを委任レベルの偽装のトークンまたは新しいプライマリ トークンに変換します。DuplicateToken
またはに関してこれを行うことができますDuplicateTokenEx
。
S4U2Self ( http://msdn.microsoft.com/en-us/magazine/cc188757.aspxおよびhttp://msdn.microsoft.com/en-us/library/ms998355.aspxを参照) を使用して、新しいトークンを受け取ります。 1 つの単純な .NET ステートメントに関する古いものWindowsIdentity wi = new WindowsIdentity(identity);
1 つの固定アカウントに関して、別のサーバーにアクセスできます。IIS のアプリケーション プールのアカウントのコンピューター アカウントにすることができます。これは、ファイル システムへのアクセスにのみ使用する別の固定定義アカウントにすることができます。
IIS が実行されているサーバーにある Windows Server のバージョンと、ドメインの Active Directory にあるドメイン機能レベルを把握しておくことが重要です (ドメインを選択すると、「Active Directory Domain and Trusts」ツールでこれが表示されます)。をクリックし、[ドメインの機能レベルを上げる] を選択します)。また、IIS のアプリケーション プールがどのアカウントで実行されているかを知ることも興味深いことです。
最初と 3 番目の方法は常に機能します。3 番目の方法は、環境やファイル システムの現在のアクセス許可に悪影響を与える可能性があります。2枚目はとてもエレガントです。IIS からアクセスするサーバー (ファイル サーバー) を制御できます。この方法にはいくつかの制限があり、Active Directory でいくつかの作業を行う必要があります。
従来の ASP を使用しているため、実装をサポートするために小さなスクリプト可能なソフトウェア コンポーネントを作成する必要があります。
あなたはどちらの方法を好みますか?
コメントからの質問に基づいて更新: 従来の ASP を使用しているため、Win32 API を直接使用することはできませんが、必要な API を使用する VB6 または .NET で小さな COM コンポーネントを作成できます。例として、 http://support.microsoft.com/kb/248187/enのコードを使用できます。ただし、内部で他のことを行う必要があります。そこで、トークンと偽装で必要なことをすべて行うのにどの Win32 API が役立つかを説明します。
まず、なりすましについて簡単に説明します。すべてが非常に簡単に機能します。プロセスが実行されるプライマリ トークンは常に 1 つです。どのスレッドにも、別のトークン (スレッド トークン) を割り当てることができます。これを行うには、ユーザーのトークンを取得してhUserToken
API を呼び出す必要がありますImpersonateLoggedOnUser(hUserToken);
。
元のプロセス トークンに戻るには (現在のスレッドのみ)、RevertToSelf()
関数を呼び出すことができます。Web サイトをそのように構成したため、ユーザーのトークンが IIS によって受信され、既に偽装されます。元のプロセス トークンに戻るにはRevertToSelf()
、カスタム COM コンポーネントで関数の呼び出しを実装する必要があります。おそらく、ASP ページで何もする必要がなければそれで十分ですが、ファイルを操作する前に現在のユーザーのトークンを変数に保存することをお勧めします。次に、ファイル システムですべての操作を行い、最後にユーザー トークンを現在のスレッドに再割り当てします。に関して、偽装トークンをスレッドに割り当てることができますSetThreadToken(NULL,hUserToken);
。現在のスレッドトークン(あなたの場合はユーザートークン)を与える(保存する)には、OpenThreadToken
APIを使用できます。それはうまくいくはずです。
更新2: おそらく、 1 つの ASP ページの最後RevertToSelf()
での関数の使用は、既に問題ないでしょう。対応する C# コードは次のようになります。
という名前の「クラス ライブラリ」タイプの C# で新しいプロジェクトを作成しますLoginAdmin
。内部に次のコードを貼り付けます
using System;
using System.Runtime.InteropServices;
namespace LoginAdmin {
[InterfaceTypeAttribute (ComInterfaceType.InterfaceIsDual)]
public interface IUserImpersonate {
[DispId(1)]
bool RevertToSelf ();
}
internal static class NativeMethods {
[DllImport ("advapi32.dll", SetLastError = true)]
internal static extern bool RevertToSelf ();
}
[ClassInterface (ClassInterfaceType.AutoDual)]
public class UserImpersonate : IUserImpersonate {
public UserImpersonate () { }
public bool RevertToSelf () {
return NativeMethods.RevertToSelf();
}
}
}
「ビルド」部分の「COM相互運用の登録」でプロジェクトのプロパティをチェックインします。プロジェクトの "Signing" 部分で Sign the assembly をチェックし、"Choose a strong name key file" で を選択<New...>
し、任意のファイル名とパスワードを入力します (または "protect my key..." をオフにします)。最後に、プロジェクトのプロパティ部分で AssemblyInfo.cs の行を変更する必要があります。
[assembly: ComVisible (true)]
このプロジェクトをコンパイルすると、LoginAdmin.dll と LoginAdmin.tlb の 2 つのファイルが得られます。DLL は、現在のコンピューターに既に登録されています。登録するには、他のコンピューターでRegAsm.exeを使用します。
この COM DLL を ASP ページでテストするには、次のようにします。
<%@ Language="javascript" %>
<html><body>
<% var objNet = Server.CreateObject("WScript.Network");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var objLoginAdmin = Server.CreateObject("LoginAdmin.UserImpersonate");
var isOK = objLoginAdmin.RevertToSelf();
if (isOK)
Response.Write("RevertToSelf return true<br/>");
else
Response.Write("RevertToSelf return false<br/>");
Response.Write("One more time after RevertToSelf()<br/>");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var fso = Server.CreateObject("Scripting.FileSystemObject");
var path = "\\\\mk01\\C\\Oleg";
if (fso.FolderExists(path)) {
Response.Write("Yes");
} else {
Response.Write("No");
}%>
</body></html>
IIS アプリケーション プールの実行に使用されるアカウントが、対応するネットワーク共有にアクセスできる場合、出力は次のようになります。
Current user: Oleg
Current user's domain: WORKGROUP
RevertToSelf return true
One more time after RevertToSelf()
Current user: DefaultAppPool
Current user's domain: WORKGROUP
Yes