我曾经成功地使用windows程序成功的创建了一批带邮箱的域帐户但是当我把这段代码交给我的一个同事(她负责开发Web应用)迁移到中后只能创建域帐户不能创建邮箱为什么呢?
我们咨询了微软的工程师他告诉我们这是由于的权限不够我们应该在模拟用户这样就可以成功创建
我将微软的相关文章摘录下来
模拟 IIS 验证的帐户或用户
若要在收到 ASPNET 应用程序中每个页的每个请求时模拟 Microsoft Internet 信息服务 (IIS) 身份验证用户必须在此应用程序的 nfig 文件中包含 <identity> 标记并将 impersonate 属性设置为 true例如
<identity impersonate=true />
为 ASPNET 应用程序的所有请求模拟特定用户
若要为 ASPNET 应用程序的所有页面上的所有请求模拟特定用户可以在该应用程序的 nfig 文件的 <identity> 标记中指定 userName 和 password 属性例如
<identity impersonate=true userName=accountname password=password />
注意在线程上模拟特定用户的进程的标识必须具有作为操作系统的一部分权限默认情况下Aspnet_wpexe 进程在名为 ASPNET 的计算机帐户下运行不过此帐户没有模拟特定用户所需的权限如果您尝试模拟特定用户则会出现一条错误信息
要解决此问题请使用下列方法之一
为 ASPNET 帐户(权限最低的帐户)授予作为操作系统的一部分权限
注意虽然此方法可以解决问题但 Microsoft 不建议使用此方法
在 nfig 文件的 <processModel> 配置部分中将运行 Aspnet_wpexe 进程所使用的帐户更改为 System 帐户
在代码中模拟身份验证用户
若要仅在运行代码特定部分时模拟身份验证用户 (UserIdentity)您可以使用以下代码此方法要求身份验证用户标识的类型为 WindowsIdentity
Visual Basic NET
Dim impersonationContext As SystemSecurityPrincipalWindowsImpersonationContext Dim currentWindowsIdentity As SystemSecurityPrincipalWindowsIdentity currentWindowsIdentity = CType(UserIdentity SystemSecurityPrincipalWindowsIdentity)
impersonationContext = currentWindowsIdentityImpersonate()
Insert your code that runs under the security context of the authenticating user here impersonationContextUndo()
Visual C# NET
SystemSecurityPrincipalWindowsImpersonationContext impersonationContextimpersonationContext =((SystemSecurityPrincipalWindowsIdentity)UserIdentity)Impersonate()//Insert your code that runs under the security context of the authenticating user here impersonationContextUndo()
Visual J# NET
SystemSecurityPrincipalWindowsImpersonationContext impersonationContextimpersonationContext =((SystemSecurityPrincipalWindowsIdentity)get_User()get_Identity())Impersonate()//Insert your code that runs under the security context of the authenticating user here impersonationContextUndo()
在代码中模拟特定用户
若要仅在运行代码特定部分时模拟特定用户请使用以下代码
Visual Basic NET
<%@ Page Language=VB %> <%@ Import Namespace = SystemWeb %> <%@ Import Namespace = SystemWebSecurity %> <%@ Import Namespace = SystemSecurityPrincipal %> <%@ Import Namespace = SystemRuntimeInteropServices %> <script runat=server> Dim LOGON_LOGON_INTERACTIVE As Integer = Dim LOGON_PROVIDER_DEFAULT As Integer = Dim impersonationContext As WindowsImpersonationContext Declare Function LogonUserA Lib advapidll (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 Declare Auto Function DuplicateToken Lib advapidll ( _ ByVal ExistingTokenHandle As IntPtr _ ByVal ImpersonationLevel As Integer _ ByRef DuplicateTokenHandle As IntPtr) As Integer Declare Auto Function RevertToSelf Lib advapidll () As Long Declare Auto Function CloseHandle Lib kerneldll (ByVal handle As IntPtr) As Long Public Sub Page_Load(ByVal s As Object ByVal e As EventArgs)
If impersonateValidUser(username domain password) Then Insert your code that runs under the security context of a specific user here undoImpersonation()
Else Your impersonation failed Therefore include a failsafe mechanism here End If End Sub Private Function impersonateValidUser(ByVal userName As String _ ByVal domain As String ByVal password As String) As Boolean Dim tempWindowsIdentity As WindowsIdentity Dim token As IntPtr = IntPtrZero Dim tokenDuplicate As IntPtr = IntPtrZero impersonateValidUser = False If RevertToSelf() Then If LogonUserA(userName domain password LOGON_LOGON_INTERACTIVELOGON_PROVIDER_DEFAULT token) <> Then If DuplicateToken(token tokenDuplicate) <> Then tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentityImpersonate()
If Not impersonationContext Is Nothing Then impersonateValidUser = True End If If Not tokenDuplicateEquals(IntPtrZero) Then CloseHandle(tokenDuplicate)
End If If Not tokenEquals(IntPtrZero) Then CloseHandle(token)
End If End Function Private Sub undoImpersonation()
impersonationContextUndo()
End Sub </script>
Visual C# NET
<%@ Page Language=C#%> <%@ Import Namespace = SystemWeb %> <%@ Import Namespace = SystemWebSecurity %> <%@ Import Namespace = SystemSecurityPrincipal %> <%@ Import Namespace = SystemRuntimeInteropServices %> <script runat=server> public const int LOGON_LOGON_INTERACTIVE = public const int LOGON_PROVIDER_DEFAULT = WindowsImpersonationContext impersonationContext[DllImport(advapidll)] public static extern int LogonUserA(String lpszUserNameString lpszDomainString lpszPasswordint dwLogonTypeint dwLogonProviderref IntPtr phToken)[DllImport(advapidll CharSet=CharSetAuto SetLastError=true)] public static extern int DuplicateToken(IntPtr hTokenint impersonationLevelref IntPtr hNewToken)[DllImport(advapidll CharSet=CharSetAuto SetLastError=true)] public static extern bool RevertToSelf()[DllImport(kerneldll CharSet=CharSetAuto)] public static extern bool CloseHandle(IntPtr handle)public void Page_Load(Object s EventArgs e)
{ if(impersonateValidUser(username domain password))
{ //Insert your code that runs under the security context of a specific user here undoImpersonation()} else { //Your impersonation failed Therefore include a failsafe mechanism here } private bool impersonateValidUser(String userName String domain String password)
{ WindowsIdentity tempWindowsIdentityIntPtr token = IntPtrZeroIntPtr tokenDuplicate = IntPtrZeroif(RevertToSelf())
{ if(LogonUserA(userName domain password LOGON_LOGON_INTERACTIVELOGON_PROVIDER_DEFAULT ref token) != )
{ if(DuplicateToken(token ref tokenDuplicate) != )
{ tempWindowsIdentity = new WindowsIdentity(tokenDuplicate)impersonationContext = tempWindowsIdentityImpersonate()if (impersonationContext != null)
{ CloseHandle(token)CloseHandle(tokenDuplicate)return true} if(token!= IntPtrZero)
CloseHandle(token)if(tokenDuplicate!=IntPtrZero)
CloseHandle(tokenDuplicate)return false} private void undoImpersonation()
{ impersonationContextUndo()} </script>
Visual J# NET
<%@ Page language=VJ# %> <%@ Import Namespace=SystemWeb %> <%@ Import Namespace=SystemWebSecurity %> <%@ Import Namespace=SystemSecurityPrincipal %> <%@ Import Namespace=SystemRuntimeInteropServices %> <script runat=server> public static int LOGON_LOGON_INTERACTIVE = public static int LOGON_PROVIDER_DEFAULT = WindowsImpersonationContext impersonationContext/** @attribute DllImport(advapidll) */ public static native int LogonUserA(String lpszUserNameString lpszDomainString lpszPasswordint dwLogonTypeint dwLogonProviderSystemIntPtr[] phToken)/** @attribute DllImport(advapidllCharSet=CharSetAuto SetLastError=true) */ public static native int DuplicateToken(SystemIntPtr hTokenint impersonationLevelSystemIntPtr[] hNewToken)/** @attribute DllImport(kerneldllCharSet=CharSetAuto) */ public static native boolean CloseHandle(SystemIntPtr[] handle)/** @attribute DllImport(advapidllCharSet=CharSetAutoSetLastError=true) */ public static native boolean RevertToSelf()public void Page_Load(Object s SystemEventArgs e)
{ if(impersonateValidUser(username domain password))
{ //Insert your code that runs under the security context of a specific user here undoImpersonation()} else { //Your impersonation failed Therefore include a failsafe mechanism here } private boolean impersonateValidUser(String userName String domain String password)
{ WindowsIdentity tempWindowsIdentitySystemIntPtr[] token = new SystemIntPtr[]SystemIntPtr[] tokenDuplicate = new SystemIntPtr[]if(RevertToSelf())
{ if(LogonUserA(userName domain password LOGON_LOGON_INTERACTIVELOGON_PROVIDER_DEFAULT token) != )
{ if(DuplicateToken(token[] tokenDuplicate) != )
{ tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[])impersonationContext = tempWindowsIdentityImpersonate()if (impersonationContext != null)
{ CloseHandle(tokenDuplicate)CloseHandle(token)return true} if(!token[]Equals(SystemIntPtrZero))
CloseHandle(token)if(!tokenDuplicate[]Equals(SystemIntPtrZero))
CloseHandle(tokenDuplicate)return false} private void undoImpersonation()
{ impersonationContextUndo()} </script>
注意在线程上模拟特定用户的进程的标识必须具有作为操作系统的一部分权限默认情况下Aspnet_wpexe 进程在名为 ASPNET 的计算机帐户下运行不过此帐户没有模拟特定用户所需的权限如果您尝试模拟特定用户则会出现一条错误信息
要解决此问题请使用下列方法之一
为 ASPNET 帐户授予作为操作系统的一部分权限
在 nfig 文件的 <processModel> 配置部分中将运行 Aspnet_wpexe 进程所使用的帐户更改为 System 帐户