本文只描述一些关键点,详细信息请参考文后msdn 文章。
有时上传的图片或文件太多,就考虑向网络盘上传图片或文件,这个时候如果还像本地上传图片那样,应用程序就会报错:Could not find a part of the path //ip/filepath
解决这个问题必须先了解asp.net的安全体系,用身份模拟的方法使得读写文件成行。
关键词:身份模拟
缺省情况下,ASP.NET应用程序以本机的ASPNET帐号运行,该帐号属于普通用户组,权限受到一定的限制,以保障ASP.NET应用程序运行的安全。但是有时需要某个ASP.NET应用程序或者程序中的某段代码执行需要特定权限的操作,比如某个文件的存取,这时就需要给该程序或相应的某段代码赋予某个帐号的权限以执行该操作,这种方法称之为身份模拟(Impersonation)。
需要设置一个专有的域用户用来执行该操作。在此条件下通常有两种方式:
在ASP.NET应用程序中使用身份模拟Impersonation
1. 配置web.config
<identity impersonate="true" userName="domain/accountname" password="password" />
2.代码中模拟指定的用户帐号更加灵活,只作用于要访问资源的代码段。实例代码参考:
//模拟帐户
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Configuration;
public class YourClass
{
//模拟帐户信息
private string ImpersonateDomainName;
private string ImpersonateAccountName;
private string ImpersonateAccountPassword;
public YourClass()
{
//构造函数得到模拟帐户信息,从web.config里配置得到
ImpersonateDomainName=ConfigurationSettings.AppSettings["ImpersonateDomainName"].ToString();
ImpersonateAccountName=ConfigurationSettings.AppSettings["ImpersonateAccountName"].ToString();
ImpersonateAccountPassword=ConfigurationSettings.AppSettings["ImpersonateAccountPassword"].ToString();
}
#region 模拟身份验证
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
public extern static int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
#endregion
#region 图片
#region 模拟身份验证
private bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
return true;
else
return false;
}
else
return false;
}
else
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
#endregion
/// <summary>
/// 得到指定资源库中所有图片列表
/// </summary>
/// <param name="iNo"></param>
/// <returns></returns>
public DataTable GetPictureLib(int iNo)
{
//返回表 PicLib:iNo,PicName
try
{
if(impersonateValidUser(ImpersonateAccountName, ImpersonateDomainName, ImpersonateAccountPassword))
{
//Insert your code that runs under the security context of a specific user here.
#region 获得图片库
string SubPath="temp";
string PicPathV="../picturelib/" + SubPath+"/"+iNo+"/";
string PicPath=HttpContext.Current.Server.MapPath(PicPathV);
DataTable tb=new DataTable("PicLib");
tb.Columns.Add("iNo",typeof(System.Int32));
tb.Columns.Add("PicName",typeof(System.String));
//是否存在此目录
if (!Directory.Exists(PicPath))
{
return null;
}
DirectoryInfo dir = new DirectoryInfo(PicPath);
FileSystemInfo[] entryies = dir.GetFileSystemInfos();
FileSystemInfo file;
for (int i=0;i<entryies.Length;i++)
{
file=entryies[i];
//如果是一个文件
if(file.GetType()==typeof(FileInfo) && (file.Extension.ToLower()==".jpg" || file.Extension.ToLower()==".gif" || file.Extension.ToLower()==".jpeg") )
{
DataRow dr=tb.NewRow();
dr["iNo"]=iNo;
dr["PicName"]=file.Name;
tb.Rows.Add(dr);
}
}
#endregion
undoImpersonation();
return tb;
}
else
{
//Your impersonation failed. Therefore, include a fail-safe mechanism here.
throw new Exception("没有操作资源的权限,请确认管理员域用户权限,IIS或Web.Config配置正确!");
}
}
catch(Exception ex)
{
throw(ex);
}
}
/// <summary>
/// 得到上传文件路经里的文件名
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
private string getFileName(string fileName)
{
int position;
position=fileName.LastIndexOf("//");
return fileName.Substring(position+1);
}
/// <summary>
/// 得到文件名的扩展名
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
private string getExtendedName(string fileName)
{
int position;
position=fileName.LastIndexOf(".");
return fileName.Substring(position);
}
/// <summary>
/// 得到数字随机串
/// </summary>
/// <returns></returns>
private string GetNumberRandom()
{
int intNum;
long lngNum;
string strNum = System.DateTime.Now.ToString("G");
strNum = strNum.Replace(":","");
strNum = strNum.Replace("-","");
strNum = strNum.Replace(" ","");
strNum = strNum.Replace("/","");
strNum = strNum.Replace("PM","1");
strNum = strNum.Replace("AM","0");
lngNum = long.Parse(strNum);
System.Random ran = new Random();
intNum = ran.Next(1,99999);
ran= null;
lngNum +=intNum;
return lngNum.ToString();
}
/// <summary>
/// 上传图片时将数据保存到服务器文件夹里
/// </summary>
/// <param name="iNo"></param>
/// <param name="PicName"></param>
public void UploadPictureToLib(int iNo,string PicName,System.Web.UI.HtmlControls.HtmlInputFile myFile)
{
try
{
if(impersonateValidUser(ImpersonateAccountName, ImpersonateDomainName, ImpersonateAccountPassword))
{
//Insert your code that runs under the security context of a specific user here.
#region 上传图片库操作
string SubPath="temp";
string PicPathV="../picturelib/" + SubPath+"/"+iNo+"/";
string PicPath=HttpContext.Current.Server.MapPath(PicPathV);
//是否存在此目录
if (!Directory.Exists(PicPath))
{
Directory.CreateDirectory(PicPath);
}
//保存上传的图片
string tmpFileName=getFileName(myFile.PostedFile.FileName);
if(tmpFileName.IndexOf(".")>0 )
{
string tmpExtendedName=getExtendedName(tmpFileName);
if(tmpExtendedName.ToLower()==".jpg" || tmpExtendedName.ToLower()==".gif" || tmpExtendedName.ToLower()==".jpeg")
{
tmpFileName=GetNumberRandom()+tmpExtendedName.ToLower();
myFile.PostedFile.SaveAs(PicPath+tmpFileName);
}
else
throw new Exception("11104");
}
#endregion
undoImpersonation();
}
else
{
//Your impersonation failed. Therefore, include a fail-safe mechanism here.
throw new Exception("没有操作资源的权限,请确认管理员域用户权限,IIS或Web.Config配置正确!");
}
}
catch(Exception ex)
{
throw(ex);
}
}
#endregion
}
注:iis设置网盘虚拟路径,关键是要把本来默认是本地的虚拟路径连接和目录安全变成域的方式。
1.建虚路径时将路径项手工填入网络地址。
2.完成向导后到属性(properties),主路径(home directory)中选择资源来自(the content for this recources should come from),另一台机器的共享路径 (a share located in another computer),纠正填写网络路径,连接为(connected as),填入你准备的域用户帐号。
3.路径安全性(directory secutity),验证和访问控制(authentication and access control),帐户信息改为你的域用户帐户
访问以下链接获取更多信息:
http://www.cnblogs.com/drw/articles/17946.html
1. INFO: Implementing Impersonation in an ASP.NET Application
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158&SD=MSKB
2. INFO: ASP.NET Security Overview
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306590
3. ASP.NET Web Application Security
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspnetwebapplicationsecurity.asp