我曾經成功地使用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 帳戶
From:http://tw.wingwit.com/Article/program/net/201311/12774.html