在 ASP.NET 应用程序中实现模拟--Impersonation

        缺省情况下,ASP.NET应用程序以本机的ASPNET帐号运行,该帐号属于普通用户组,权限受到一定的限制,以保ASP.NET应用程序运行的安全。但是有时需要某个ASP.NET应用程序或者程序中的某段代码执行需要特定权限的操作,比如某个文件的存取,这时就需要给该程序或相应的某段代码赋予某个帐号的权限以执行该操作,这种方法称之为身份模拟(Impersonation)。

        如果要在 ASP.NET 中的线程上模拟用户,可以根据您的要求使用以下方法之一:

        注意:可以使用以下代码来确定线程作为哪个用户执行:

System.Security.Principal.WindowsIdentity.GetCurrent().Name

        模拟 IIS 验证的帐户或用户

        若要在收到 ASP.NET 应用程序中每个页的每个请求时模拟 Microsoft Internet 信息服务 (IIS) 身份验证用户,必须在此应用程序的 Web.config 文件中包含 <identity> 标记,并将 impersonate属性设置为 true。例如:

<identity impersonate="true" />

        为 ASP.NET 应用程序的所有请求模拟特定用户

        若要为 ASP.NET 应用程序的所有页面上的所有请求模拟特定用户,可以在该应用程序的 Web.config 文件的 <identity> 标记中指定 userName 和 password 属性。例如: 

<identity impersonate="true" userName="accountname" password="password" />

        注意:在线程上模拟特定用户的进程的标识必须具有“作为操作系统的一部分”权限。默认情况下,Aspnet_wp.exe 进程在名为 ASPNET 的计算机帐户下运行。不过,此帐户没有模拟特定用户所需的权限。如果您尝试模拟特定用户,则会出现一条错误信息。此信息只适用于 .NET Framework 1.0。.NET Framework 1.1 不要求此权限。

        要解决此问题,请使用下列方法之一:

        a. 为 ASPNET 帐户(权限最低的帐户)授予“作为操作系统的一部分”权限。

            注意:虽然此方法可以解决问题,但 Microsoft 不建议使用此方法。

        b. 在 Machine.config 文件的 <processModel> 配置节中,将运行 Aspnet_wp.exe 进程所使用的帐户更改为 System 帐户。

        在代码中模拟身份验证用户

        若要仅在运行代码的特定部分时模拟身份验证用户 (User.Identity),您可以使用以下代码。此方法要求身份验证用户标识的类型为 WindowsIdentity
代码
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

        在代码中模拟特定用户

        若要仅在运行代码的特定部分时模拟特定用户,请使用以下代码:

代码
<%@ Page Language="C#"%>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>

<script runat=server>
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext; 

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, 
    String lpszDomain,
    String lpszPassword,
    
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 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 fail-safe mechanism here.
    }
}

private bool impersonateValidUser(String userName, String domain, String password)
{
    WindowsIdentity tempWindowsIdentity;
    IntPtr token = IntPtr.Zero;
    IntPtr tokenDuplicate = IntPtr.Zero;

    
if(RevertToSelf())
    {
        
if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
            LOGON32_PROVIDER_DEFAULT, ref token) != 0)
        {
            
if(DuplicateToken(token, 2ref tokenDuplicate) != 0
            {
                tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                impersonationContext = tempWindowsIdentity.Impersonate();
                
if (impersonationContext != null)
                {
                    CloseHandle(token);
                    CloseHandle(tokenDuplicate);
                    
return true;
                }
            }
        } 
    }
    
if(token!= IntPtr.Zero)
        CloseHandle(token);
    
if(tokenDuplicate!=IntPtr.Zero)
        CloseHandle(tokenDuplicate);
    
return false;
}

private void undoImpersonation()
{
    impersonationContext.Undo();
}
</script>
        注意:在线程上模拟特定用户的进程的标识必须具有“作为操作系统的一部分”权限。默认情况下,Aspnet_wp.exe 进程在名为 ASPNET 的计算机帐户下运行。不过,此帐户没有模拟特定用户所需的权限。如果您尝试模拟特定用户,则会出现一条错误信息。此信息只适用于 .NET Framework 1.0。.NET Framework 1.1 不要求此权限。

        要解决此问题,请使用下列方法之一:

        a. 为 ASPNET 帐户授予“作为操作系统的一部分”权限。

            注意:我们不建议使用这种方法解决此问题。 b. 在 Machine.config 文件的 <processModel> 配置节中,将运行 Aspnet_wp.exe 进程所使用的帐户更改为 System 帐户。

        b. 在 Machine.config 文件的 <processModel> 配置节中,将运行 Aspnet_wp.exe 进程所使用的帐户更改为 System 帐户。


 

 MSDN资源:在ASP.NET应用程序中使用身份模拟(Impersonation)

 

posted @ 2010-11-08 15:26  witrays  阅读(372)  评论(0)    收藏  举报