关于ASP.NET中的身份模拟说明
Asp.net默认运行的帐号在未经授权时通常是不具有对文件夹的写权限的,这时,试图进行磁盘写操作的程序将会抛出异常,例如如下代码:
FileStream fsMyfile =
new FileStream("c://test.txt",FileMode.Create,FileAccess.ReadWrite);
byte[] bytes1 =System.Text.Encoding.UTF8.GetBytes( "写文件的内容" );
fsMyfile.Write(bytes1,0,bytes1.Length);
fsMyfile.Flush();
fsMyfile.Close();
运行该部分代码,会得到如下异常信息
解决该问题的方法之一就是将所访问的文件夹的写权限授予ASP.NET这个帐号,这个帐号就是asp.net默认使用的帐号,但是,通常我们不希望这么做,我们往往希望使用管理员为程序开发人员设定的某个特定的帐号进行文件写操作,这时,就需要使用“身份模拟”,即临时使用某个具有特定权限的帐号执行程序,执行完毕后再关闭身份模拟,即程序结构如下:
使用默认帐号执行代码部分
开始模拟特定帐号
在特定帐号下执行代码部分
解除模拟特定帐号
使用默认帐号执行代码部分
其中红色部分就是需要特殊权限才能执行的代码部分,通常可能是对文件夹或文件的写操作等。这样,前面运行抛出异常的程序将可以使用如下方式进行改写:
HTECP.Authority.IdentityAnalogue ia = new HTECP.Authority.IdentityAnalogue();
if(
ia.impersonateValidUser("FuWaer","developer.com","123456789") )
{
FileStream fsMyfile = new FileStream("c://test.txt",FileMode.Create,FileAccess.ReadWrite);
byte[] bytes1 =System.Text.Encoding.UTF8.GetBytes( "写文件的内容" );
fsMyfile.Write(bytes1,0,bytes1.Length);
fsMyfile.Flush();
fsMyfile.Close();
ia.undoImpersonation();
}
else
{
Page.Response.Write("身份模拟失败");
}
其中,红色粗体代码就是需要增加的身份模拟的代码,身份模拟代码被封装到了HTECP.Authority.IdentityAnalogue类中,主要有两个函数:
public
bool impersonateValidUser(string userName,string domain,string password)
public
void undoImpersonation()
其中,impersonateValidUser是开始以特定帐号执行身份模拟的函数,如果该函数执行成功,则后继代码将以该特定帐号的权限进行执行;
当不再需要使用特定帐号执行程序时,使用undoImpersonation函数解除特定帐号身份的模拟。
为避免对特定帐号的程序硬编码,通常需要使用身份模拟的项目,在web.config中进行如下配置
<
addkey="IdentityAnalogue"value="FuWaer;developer.com;123456789">add>
附IdentityAnalogue:
public
class
IdentityAnalogue
...
{
//模拟指定用户时使用的常量定义
/**////
///
///
public const int LOGON32_LOGON_INTERACTIVE = 2;
/**////
///
///
public const int LOGON32_PROVIDER_DEFAULT = 0;
/**////
///
///
WindowsImpersonationContext impersonationContext;
//win32api引用
/**////
///
///
///
///
///
///
///
///
///
[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 IdentityAnalogue()
...{
}
//模拟指定的用户身份
/**////
///
///
///
///
///
///
public 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,2,0,ref token)!=0)
...{
if(DuplicateToken(token,2,ref 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;
}
//取消模拟
/**////
///
///
public void undoImpersonation()
...{
impersonationContext.Undo();
}
}