以前、Windows プログラムを使用してメールボックスを含むドメイン アカウントのバッチを作成することに成功しましたが、このコードを同僚の 1 人 (彼女は Web アプリケーションの開発を担当していました) に渡して asp.net に移行したところ、ドメインの作成しかできませんでした。アカウントではメールボックスを作成できません。なぜ?
Microsoft のエンジニアに相談したところ、これは asp.net の権限が不十分であるため、正常に作成できるように asp.net でユーザーをシミュレートする必要があるとのことでした。
Microsoft から関連記事を抜粋しました。
IIS 認証されたアカウントまたはユーザーになりすます
ASP.NET アプリケーションのすべてのページに対するすべての要求を受信するときに Microsoft インターネット インフォメーション サービス (IIS) 認証されたユーザーになりすますには、このアプリケーションの <identity> タグを Web.config ファイルに含める必要があります。そして、impersonate 属性を true に設定します。例:
<identity impersonate="true" />
ASP.NET アプリケーションへのすべての要求に対して特定のユーザーを偽装する
ASP.NET アプリケーションのすべてのページのすべての要求に対して特定のユーザーを偽装するには、userName 属性とpassword 属性を指定できます。例:
<identity impersonate="true" userName="アカウント名" パスワード="パスワード" />
注: スレッド上で特定のユーザーを偽装するプロセスの ID には、「オペレーティング システムの一部として」権限が必要です。デフォルトでは、Aspnet_wp.exe プロセスは ASPNET という名前のコンピューター アカウントで実行されます。ただし、このアカウントには、特定のユーザーになりすますために必要な権限がありません。特定のユーザーになりすますと、エラー メッセージが表示されます。
この問題を解決するには、次のいずれかの方法を使用します。
?
ASPNET アカウント (最も権限の低いアカウント) に「オペレーティング システムの一部として機能する」アクセス許可を付与します。
注: この方法で問題が解決される可能性がありますが、Microsoft はこの方法をお勧めしません。
?
Machine.config ファイルの <processModel> 構成セクションで、Aspnet_wp.exe プロセスを実行するアカウントをシステム アカウントに変更します。
コードで認証されたユーザーを偽装する
コードの特定の部分を実行する場合にのみ認証されたユーザー (User.Identity) を偽装するには、次のコードを使用できます。この方法では、認証ユーザー ID の種類が WindowsIdentity である必要があります。
Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext
currentWindowsIdentity を System.Security.Principal.WindowsIdentity として薄暗くする
currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()
' 認証ユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
impersonationContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
偽装コンテキスト =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
// 認証ユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
impersonationContext.Undo();
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
偽装コンテキスト =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();
// 認証ユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
impersonationContext.Undo();
コード内で特定のユーザーを偽装する
コードの特定の部分を実行する場合にのみ特定のユーザーを偽装するには、次のコードを使用します。
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ インポート名前空間 = "System.Web" %>
<%@ インポート名前空間 = "System.Web.Security" %>
<%@ インポート名前空間 = "System.Security.Principal" %>
<%@ インポート名前空間 = "System.Runtime.InteropServices" %>
<スクリプト runat=サーバー>
整数 = 2 として DIM LOGON32_LOGON_INTERACTIVE
整数 = 0 として DIM LOGON32_PROVIDER_DEFAULT
WindowsImpersonationContext としての薄暗い impersonationContext
関数 LogonUserA Lib "advapi32.dll" を宣言します (ByVal lpszUsername As String, _
ByVal lpszDomain を文字列として、_
ByVal lpsz文字列としてのパスワード、_
ByVal dwLogonType を整数として、_
ByVal dwLogonProvider を整数として、_
ByRef phToken As IntPtr) As Integer
Auto Function DuplicateToken Lib "advapi32.dll" を宣言します ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer、_
ByRef DuplicateTokenHandle As IntPtr) As Integer
自動関数 RevertToSelf Lib "advapi32.dll" () を長く宣言します
Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long を宣言
Public Sub Page_Load(ByVal をオブジェクトとして、ByVal e を EventArgs として)
impersonateValidUser("ユーザー名", "ドメイン", "パスワード") の場合
'特定のユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
undoImpersonation()
それ以外
「偽装は失敗しました。したがって、ここにフェイルセーフ機構を含めてください。」
終了の場合
エンドサブ
プライベート関数 impersonateValidUser(ByVal userName As String, _
ByVal ドメイン (文字列として)、ByVal パスワード (文字列として)) ブール値として
WindowsIdentity としての薄暗い WindowsIdentity
Dim トークン As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
RevertToSelf() の場合
LogonUserA(ユーザー名、ドメイン、パスワード、LOGON32_LOGON_INTERACTIVE,
Logon32_PROVIDER_DEFAULT、トークン) <> 0 次に
If DuplicateToken(token, 2, tokenDuplicate) <> 0 then
tempWindowsIdentity = 新しい WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
impersonationContext が何もない場合
impersonateValidUser = True
終了の場合
終了の場合
終了の場合
終了の場合
tokenDuplicate.Equals(IntPtr.Zero) でない場合
CloseHandle(トークン重複)
終了の場合
token.Equals(IntPtr.Zero) でない場合
CloseHandle(トークン)
終了の場合
終了機能
プライベートサブ undoImpersonation()
impersonationContext.Undo()
エンドサブ
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ インポート名前空間 = "System.Web" %>
<%@ インポート名前空間 = "System.Web.Security" %>
<%@ インポート名前空間 = "System.Security.Principal" %>
<%@ インポート名前空間 = "System.Runtime.InteropServices" %>
<スクリプト runat=サーバー>
public const int Logon32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
文字列 lpszDomain、
文字列 lpszパスワード、
int dwLogonType,
int dwLogonProvider、
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel、
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr ハンドル);
public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("ユーザー名", "ドメイン", "パスワード"))
{
// 特定のユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
undoImpersonation();
}
それ以外
{
//偽装は失敗しました。したがって、ここにフェイルセーフメカニズムを含めてください。
}
}
private bool impersonateValidUser(文字列のユーザー名、文字列のドメイン、文字列のパスワード)
{
WindowsIdentity tempWindowsIdentity;
IntPtr トークン = IntPtr.Zero;
IntPtr トークン重複 = IntPtr.Zero;
if(RevertToSelf())
{
if(LogonUserA(ユーザー名、ドメイン、パスワード、LOGON32_LOGON_INTERACTIVE,
Logon32_PROVIDER_DEFAULT、参照トークン) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = 新しい WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(トークン);
CloseHandle(tokenDuplicate);
true を返します。
}
}
}
}
if(トークン!= IntPtr.Zero)
CloseHandle(トークン);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
false を返します。
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
Visual J# .NET
<%@ Page language="VJ#" %>
<%@ インポート名前空間="System.Web" %>
<%@ インポート名前空間="System.Web.Security" %>
<%@ インポート名前空間="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<スクリプト runat=サーバー>
public static int Logon32_LOGON_INTERACTIVE = 2;
public static int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext
/** @attribute DllImport("advapi32.dll") */
public staticnative int LogonUserA(String lpszUserName,
文字列 lpszDomain、
文字列 lpszパスワード、
int dwLogonType,
int dwLogonProvider、
System.IntPtr[] phToken);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto、SetLastError=true) */
public staticnative int DuplicateToken(System.IntPtr hToken,
int impersonationLevel、
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
public staticative boolean CloseHandle(System.IntPtr[] ハンドル);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
パブリック静的ネイティブブール値 RevertToSelf();
public void Page_Load(Object s, System.EventArgs e)
{
if(impersonateValidUser("ユーザー名", "ドメイン", "パスワード"))
{
// 特定のユーザーのセキュリティ コンテキストで実行されるコードをここに挿入します。
undoImpersonation();
}
それ以外
{
//偽装は失敗しました。したがって、ここにフェイルセーフメカニズムを含めてください。
}
}
private boolean impersonateValidUser(文字列のユーザー名、文字列のドメイン、文字列のパスワード)
{
WindowsIdentity tempWindowsIdentity;
System.IntPtr[] トークン = 新しい System.IntPtr[1];
System.IntPtr[] tokenDuplicate = 新しい System.IntPtr[1];
if(RevertToSelf())
{
if(LogonUserA(ユーザー名、ドメイン、パスワード、LOGON32_LOGON_INTERACTIVE,
Logon32_PROVIDER_DEFAULT、トークン) != 0)
{
if(DuplicateToken(token[0], 2, tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(tokenDuplicate);
CloseHandle(トークン);
true を返します。
}
}
}
}
if(!token[0].Equals(System.IntPtr.Zero))
CloseHandle(トークン);
if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
CloseHandle(tokenDuplicate);
false を返します。
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
注: スレッド上で特定のユーザーを偽装するプロセスの ID には、「オペレーティング システムの一部として」権限が必要です。デフォルトでは、Aspnet_wp.exe プロセスは ASPNET という名前のコンピューター アカウントで実行されます。ただし、このアカウントには、特定のユーザーになりすますために必要な権限がありません。特定のユーザーになりすますと、エラー メッセージが表示されます。
この問題を解決するには、次のいずれかの方法を使用します。
?
ASPNET アカウントに「オペレーティング システムの一部として機能する」権限を付与します。
?
Machine.config ファイルの <processModel> 構成セクションで、Aspnet_wp.exe プロセスを実行するアカウントをシステム アカウントに変更します。