英文:
How to Access Files in ASP.NET Web Forms Application via Virtual Directory on Network Location?
问题
Processing files in a virtual directory under IIS is successful when the client is on the server but fails when the client is on another PC on the network.
我们在IIS下的虚拟目录中处理文件时,当客户端位于服务器上时成功,但当客户端位于网络上的另一台PC上时失败。
We have an ASP.NET Web Forms application (c#) that accesses TIF files via a virtual directory pointing at a network location. For example, virtual directory named corpfiles
points at \\FileServer\share
. The application is an intranet site using Windows Authentication, and the users have access to the file share.
我们有一个ASP.NET Web Forms应用程序(C#),它通过指向网络位置的虚拟目录访问TIF文件。例如,虚拟目录名为corpfiles
,指向\\FileServer\share
。该应用程序是一个使用Windows身份验证的内部网站,用户可以访问文件共享。
The web site is passed a number of URLs for TIF files on a page, e.g., ./corpfiles/file1.tif
, ./corpfiles/file2.tif
, etc. For each URL that ends in .tif
the page (this code is in the page.aspx.cs
code behind file):
网站在页面上传递了许多TIF文件的URL,例如,./corpfiles/file1.tif
,./corpfiles/file2.tif
等。对于每个以.tif
结尾的URL,页面(此代码位于page.aspx.cs
的代码后面文件中):
-
Gets the physical file path:
var filePath = Server.MapPath(docUrl);
-
获取物理文件路径:
var filePath = Server.MapPath(docUrl);
-
Ensures the file exists:
if (File.Exists(filePath))
-
确保文件存在:
if (File.Exists(filePath))
-
Converts the TIF to an in-memory PDF and presents it on the web page.
-
将TIF转换为内存中的PDF并在网页上显示。
This all works testing from Visual Studio 2022 (I added the virtual directory to my applicationhost.config
file for IIS Express), and when testing from the server hosting the site. However, the File.Exists call fails when the site is connected to from another box on the network.
这一切都在从Visual Studio 2022进行测试时正常工作(我将虚拟目录添加到IIS Express的applicationhost.config
文件中),并且在从托管该站点的服务器进行测试时也正常工作。但是,当从网络上的另一台计算机连接到该站点时,File.Exists调用会失败。
The filePath returned by Server.MapPath is valid; the user is able to access the original file directly using it.
由Server.MapPath返回的filePath是有效的;用户可以直接使用它访问原始文件。
If I don't try to access the file and just past the original URL to the user they are able to download the .tif
file without trouble. This isn't very useful since viewing the file outside of the application is clunky, but it does demonstrate they have access to the original file share.
如果我不尝试访问文件,只是将原始URL传递给用户,他们可以轻松下载.tif
文件。这并不是很有用,因为在应用程序之外查看文件很不方便,但它确实表明他们可以访问原始文件共享。
Is this a multi-hop authentication issue? We have tried supplying specific credentials on the virtual directory and using the client's credentials.
这是一个多跳身份验证问题吗?我们已尝试在虚拟目录上提供特定的凭据并使用客户端的凭据。
What am I missing?
我漏掉了什么?
英文:
Processing files in a virtual directory under IIS is successful when the client is on the server but fails when the client is on another PC on the network.
We have an ASP.NET Web Forms application (c#) that accesses TIF files via a virtual directory pointing at a network location. For example, virtual directory named corpfiles
points at \\FileServer\share
. The application is an intranet site using Windows Authentication, and the users have access to the file share.
The web site is passed a number of URLs for TIF files on a page, e.g., ./corpfiles/file1.tif
, ./corpfiles/file2.tif
, etc. For each URL that ends in .tif
the page (this code is in the page.aspx.cs
code behind file):
- Gets the physical file path:
var filePath = Server.MapPath(docUrl);
- Ensures the file exists:
if (File.Exists(filePath))
- Converts the TIF to an in-memory PDF and presents it on the web page.
This all works testing from Visual Studio 2022 (I added the virtual directory to my applicationhost.config
file for IIS Express), and when testing from the server hosting the site. However, the File.Exists call fails when the site is connected to from another box on the network.
The filePath returned by Server.MapPath is valid; the user is able to access the original file directly using it.
If I don't try to access the file and just past the original URL to the user they are able to download the .tif
file without trouble. This isn't very useful since viewing the file outside of the application is clunky, but it does demonstrate they have access to the original file share.
Is this a multi-hop authentication issue? We have tried supplying specific credentials on the virtual directory and using the client's credentials.
What am I missing?
答案1
得分: 0
请注意以下事项:
每当代码后台触及或使用文件时,使用的是完整的合法路径名。
每当URL解析为文件时,那就不是代码后台,而且您没有使用完整的Windows路径名。
但是,使用代码后台时,是的,会使用完整的常规Windows文件名和路径,也可以使用。
那么,上述内容意味着什么呢?
实际上,您实际上不需要将虚拟文件夹映射到网站,而可以完全使用代码后台来检索这些文件。
实际上,这通常是一种非常好的方法,因为这样就不会映射到网站的文件夹的有效URL。这样可以大大增强安全性。
因此,不清楚为什么 file.Exists()
失败,但请记住这是代码后台,所以需要 File.Exists("在此处输入完整的合法Windows路径和文件名")
。
所以,如果您需要向用户显示一些文件(甚至包括文件夹+文件)?
那么实际上您不必映射或使用虚拟文件夹。
但是,网站肯定需要访问网络上那些文件夹的权限 - 但用户不需要!
所以,假设我想显示一些文件(或文件夹)。
假设我不想要映射虚拟文件夹(因为那实际上是一个巨大的安全漏洞)。
因此,请记住,代码后台不使用IIS安全模型!换句话说,您甚至不必为该虚拟文件夹拥有/使用web.config,甚至不需要虚拟文件夹!
因此,这里有2个问题需要处理:
首先,您要如何向用户显示这些文件。
如果只是一个文件夹,那么简单的GridView就可以了,如果有一堆文件夹(例如嵌套文件夹),那么TreeView可能更好。
下一个问题是安全性。请记住,代码后台不关心登录的用户 - 关心的是网站用户是否有权限访问这些文件。这是因为在本讨论中,我们将放弃使用虚拟文件夹的使用,不使用IIS文件夹映射(这意味着我们绕过了IIS的安全性)。
这意味着Web服务器必须位于该网络上,这也意味着Web服务器需要访问该文件夹的权限 - 可能是其他服务器或网络存储设备(唯一的要求是这些文件夹/文件位于运行Web服务器的相同网络上)。
当然,我们需要“设置”Web站点的上下文。正如我所指出的,代码后台不关心登录的用户,IIS强制执行的安全性被完全忽略。
您没有提到Web服务器是否属于您公司的域或否。让我们假设它不是,而且出于安全原因,最好不要将Web服务器作为公司网络域的一部分。
但是,这意味着您现在需要在Web服务器上创建一个用户,一个您可以创建的用户 - 并创建一个不是域用户的用户。
然后,您需要在具有相关文件夹的服务器上创建一个用户(同名,同密码)。(再次强调,不是域用户,而是在具有文件夹+文件的服务器上创建的用户)。
现在,您所需要做的就是确保代码后台在此用户上下文中运行。
您可以右键单击应用程序池,然后选择以下选项:
所以,我们将应用程序池设置为现在以这个本地创建的用户(在本例中称为Web)运行。
我们假设您现在已经进入具有共享文件夹的服务器,并且还将此用户添加到该服务器上(再次强调,用户名和密码相同)。
因此,现在,无需虚拟文件夹,无需关心谁登录到站点,您现在可以使用代码后台获取/获取/查看/使用/浏览这些文件。但是,Web用户无论如何都不能输入URL或以任何方式获取或抓取文件。因此,这是一个很安全的设置。
唯一剩下的部分是为用户提供某种类型的UI。
所以,假设一个树形视图,可能会像这样:
而您点击任何文件,它都会被下载,但我们使用的是代码后台 - 不是合法或有效的URL路径名!(当我说合法路径名时,我指的是非虚拟和非URL路径名!)。
所以,我们得到这样的东西:
现在,在上面,我为每个文件都有复选框 - 可能不应该有。
所以,当用户点击文件时,我这样做:
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
// download this file clicked on
// user MIGHT click on a node, so not a file,
// so first check if file extension
string sFileWithPath = TreeView1.SelectedNode.Text;
FileInfo MyFile = new FileInfo(sFileWithPath);
if (File.Exists(sFileWithPath))
{
string sFileNameOnly = Path.GetFileName(sFileWithPath);
string sMineType = MimeMapping.GetMimeMapping(sFileWithPath);
FileInfo sFinfo = new FileInfo(sFileWithPath); // get lengh of file
Response.Clear();
Response.ContentType = sMineType;
Response.AppendHeader("Content-Length", sFinfo.Length.ToString());
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileNameOnly);
Response.TransmitFile(sFileWithPath);
Response.End();
}
else
{
Debug.Print("user clicked on folder");
}
}
所以,代码后台可以自由获取文件夹,遍历文件夹
英文:
Well, keep in mind the following:
Any time code behind touches or uses a file: a plain full legal path name is used.
Any time a URL resolves to a file, then it not code behind, and you are NOT using a full Windows path name.
But, with code behind, yes, a full regular Windows file name and path is used and CAN be used.
So, what does the above mean?
You actually don't need to map a virtual folder to the web site, but can use 100% code behind to retrieve such files.
This actually is often a VERY good approach, since then no valid URL's to folders are mapped though the web site. That enhances security by a LARGE margin.
So, it is not clear at all why the file.Exists()
is failing, but do keep in mind that is code behind, so File.Exists("full legal Windows path and file name goes here") is required.
So, if you need to say present some files (or even folders + files) to the user?
Then you don't actually have to map or use a virtual folder.
However, the web site WILL most certainly need rights to those folders on the network - but the users don't!
So, say I wanted to display some files (or folders).
And say I don't want a mapped virtual folder (since that is a big security hole anyway).
So, remember, code behind DOES NOT use the IIS security model! In other words, you don't even have to have/use a web.config for that virtual folder, and you don't even need the virtual folder!
So, there are 2 issues left here to deal with:
First up, how you going to display the files to the user.
A simple GridView is fine if this is just one folder, or better yet consider a TreeView if you have a bunch of folders (say nested folders).
The next issue is security. Remember, code behind does NOT care about the logged on user - it is the web site user that will (or will not) have rights to those files. This is due to for this discussion we are going to DUMP the use of a virtual folder, and NOT use IIS folder mapping here (and that means we by-pass IIS security here).
This DOES mean the web server has to be on that network, and this DOES mean the web server will need rights to that folder - could even be some other server or network storage device (only requirement is those folders/files are on the same network that running the web server).
Of course, we will have to "setup" the context of the web site. As I pointed out, code behind DOES NOT care about the logged on user, and the security enforced by IIS is 100% ignored.
You don't mention if the web server is part of your company domain or not. Let's assume it is NOT, and again a good idea to NOT have the web server as part of your company network domain anyway for reasons of security.
However, this THEN does mean that you need a user on the web server, one that you can create - and create a user that is NOT a domain user.
You will THEN need to create a user (same name, same password) on the server with the folders in question. (And again, NOT a domain user, but a user created on that server with the folders + files).
Now, all you have to do is ensure that the code behind runs with this user context.
You can right click on the app-pool, and choose this:
So, we set the app pool to run now as this local created user (called Web in this example).
And we assume you now gone to the server with the shared folders, and ALSO add this user to that server (again, same name, same password).
So, now, without a virtual folder, without caring about who logged into the site, you can now with code behind get/grab/see/use/browse those files with code behind. However, web users can not in ANY way enter a URL or in ANY way get or grab a file. So, it is a nice secure setup.
The only part left is for you to present some type of UI here.
So, say a tree view, might be like this:
And any file you click on, it will be downloaded, but we use code behind - NOT a legal or valid URL path name! (when I say legal path name, I mean a NON virtual and NON URL path name here!).
So, we get say this:
Now, in above I do have check box(s) for each file - probably should not.
So, when user clicks on a file, then I do this:
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
// download this file clicked on
// user MIGHT click on a node, so not a file,
// so first check if file extension
string sFileWithPath = TreeView1.SelectedNode.Text;
FileInfo MyFile = new FileInfo(sFileWithPath);
if (File.Exists(sFileWithPath))
{
string sFileNameOnly = Path.GetFileName(sFileWithPath);
string sMineType = MimeMapping.GetMimeMapping(sFileWithPath);
FileInfo sFinfo = new FileInfo(sFileWithPath); // get lengh of file
Response.Clear();
Response.ContentType = sMineType;
Response.AppendHeader("Content-Length", sFinfo.Length.ToString());
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileNameOnly);
Response.TransmitFile(sFileWithPath);
Response.End();
}
else
{
Debug.Print("user clicked on folder");
}
}
So, code behind is free to get folders, traverse folders, and all such code is using plain valid full Windows path names. You never have to use any Server.MapPath()
, since we never using a valid URL, and translating into a full Windows file name (that's what Server.MapPath
does) is not required any more.
So, your file.exists should work, but I would for several reasons, and one being security. I would not map those folders to the server using a Virtual folder, but ONLY use code behind, and by-pass IIS and such file mapping.
The code to display folders in a tree view: it is in fact not even recursive, and is quite easy to write.
答案2
得分: 0
问题出在凭证的委派配置不正确。域管理员需要执行以下操作:
- 为文件服务器创建一个SPN:CIFS/FILESERVER
- 确保服务账号只能使用Kerberos委派到新的SPN。
- 将服务账号授权访问FILESERVER。
现在,TIF文件的实时转换为PDF文件已经可以正常工作,用户可以在应用程序中查看PDF文件。
英文:
The problem was the delegation of credentials was not properly configured. The Domain Admin had to:
- Create an SPN for the file server: CIFS/FILESERVER
- Ensure the service account could delegate using Kerberos only to the new SPN.
- Give the service account access to the FILESERVER.
The real-time conversion of TIFs to PDFs now works with the result being the users can view the PDFs within the application.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论