I am working on a web application that allows users to upload attachments. These attachments are stored on a different drive than that of the web application. How can I create an alias (equivalent to Apache HTTP server's aliases) to this drive so that users can download these attachments?
我正在开发一个允许用户上传附件的Web应用程序。这些附件存储在与Web应用程序不同的驱动器上。如何为此驱动器创建别名(相当于Apache HTTP服务器的别名),以便用户可以下载这些附件?
Currently I am creating a context file and dumping it in CATALINA_HOME/conf/Catalina/localhost, but it gets randomly deleted every so often. The context file is named attachments.xml and the contents are shown below. I have also read about virtual hosts, but if I understand correctly, then a virtual host is not what I am looking for. I am using version 6.0.18 of Apache Tomcat.
目前我正在创建一个上下文文件并将其转储到CATALINA_HOME / conf / Catalina / localhost中,但它会经常随机删除。上下文文件名为attachments.xml,内容如下所示。我还阅读了有关虚拟主机的内容,但如果我理解正确,那么虚拟主机就不是我想要的了。我使用的是Apache Tomcat 6.0.18版。
attachments.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase = "e:\uploads\attachments"
reloadable = "true"
crossContext = "true">
</Context>
3 个解决方案
#1
9
I spent a lot more time researching this and found a solution that solves the random deletion of the context files. I found this excerpt on Apache's website under the host configuration section:
我花了很多时间研究这个,并找到了一个解决方案来解决上下文文件的随机删除问题。我在Apache的网站上在主机配置部分找到了这个摘录:
You can nest one or more Context elements inside this Host element, each representing a different web application associated with this virtual host.
您可以在此Host元素中嵌套一个或多个Context元素,每个元素表示与此虚拟主机关联的其他Web应用程序。
The virtual hosts are stored in the server.xml file located at CATALINA_HOME\conf. Tomcat comes configured with localhost as the default host. So, if we add the contents of attachments.xml from the first post, we get the following:
虚拟主机存储在位于CATALINA_HOME \ conf的server.xml文件中。 Tomcat配置了localhost作为默认主机。因此,如果我们从第一篇文章添加attachments.xml的内容,我们会得到以下内容:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context path="/attachments"
docBase="e:\uploads\attachments"
reloadable="true"
crossContext="true" />
</Host>
This is as close as one can get to defining aliases similar to Apache's HTTP server, I think.
我认为这与定义类似于Apache的HTTP服务器的别名非常接近。
#2
7
There are multiple options.
有多种选择。
- Use Apache as frontend, delegating to tomcat by mod_jk or mod_proxy
- Provide a download servlet in your own application, serving the requested file
- Make the directory that you want tomcat to deliver a web application
使用Apache作为前端,通过mod_jk或mod_proxy委托给tomcat
在您自己的应用程序中提供下载servlet,为所请求的文件提供服务
创建您希望tomcat提供Web应用程序的目录
each has some drawbacks and some advantages. I strongly prefer the first solution for multiple reasons:
每个都有一些缺点和一些优点。出于多种原因,我非常喜欢第一种解决方案:
- My main reasons apply to unixoid systems, which you are obviously not talking about: Only root can bind ports lower than 1024, e.g. 80. Therefor tomcat would need to run as root (I know that there are mechanics to allow users to bind to low ports, but I've never gotten to use them). Apache is usually started as root but drops these privileges as soon as port 80 is bound.
- Apache is said to be a lot better in serving static resources than tomcat (I've never measured it, but find it hard to believe the contrary)
- You obviously know how to create aliases in apache - it would be trivial to do so.
我的主要原因适用于unixoid系统,你显然没有谈到:只有root可以绑定低于1024的端口,例如80.因此tomcat需要以root身份运行(我知道有一些机制允许用户绑定到低端口,但我从来没有使用它们)。 Apache通常以root身份启动,但只要端口80绑定就会丢弃这些权限。
据说Apache在提供静态资源方面要比tomcat好很多(我从未测量过它,但很难相信相反)
你显然知道如何在apache中创建别名 - 这样做很简单。
About the download servlet:
关于下载servlet:
This way you'd have a servlet serving your static resources, which you might bind to the urls "/download/*" (e.g. in the application that also handles file uploads) You'd gain:
这样你就有了一个为你的静态资源提供服务的servlet,你可以将它绑定到URL“/ download / *”(例如在同样处理文件上传的应用程序中)你将获得:
- You need to configure the directory where your files are stored only once
- If you need you might easily implement permission checks (e.g. login required for downloading)
- You need to deploy only one completely selfcontained application.
- The download servlet is trivial - find the file, set it's name and filetype in the output stream and stream it byte by byte, then close the output stream (be sure to handle attacking file names like "/download/../../../../etc/passwd" or "/download/C:/WINDOWS/someimportantfile.xxx"), e.g. by using the java.io.File constructor that gets the base directory as a separate parameter.
您只需配置一次存储文件的目录
如果需要,您可以轻松实施权限检查(例如下载所需的登录)
您只需部署一个完全自包含的应用程序。
下载servlet是微不足道的 - 找到文件,在输出流中设置它的名称和文件类型并逐字节流,然后关闭输出流(确保处理攻击文件名,如“/download/../../ ../../etc/passwd“或”/download/C:/WINDOWS/someimportantfile.xxx“),例如通过使用java.io.File构造函数将获取基目录作为单独的参数。
The third option has some severe drawbacks and opens you for attacks if you don't take special care of them:
第三种选择有一些严重的缺点,如果您不特别照顾它们,可以打开攻击:
- Tomcat does not serve directories, but webapps. Therefor "E:/upload/attachments" would need at least a directory named "WEB-INF", containing "web.xml". Take care to not provide write access to this directory and file from the uploading web application. With this provision you might let tomcat serve the directory.
- However: Configure the contained web.xml to not serve "*.jsp" as a jsp, otherwise tomcat would not just deliver jsp files but execute them. Imagine someone uploading "index.jsp" with
<% System.exit(0); %>
or more malicious content.
Tomcat不提供目录,而是提供webapps。因此,“E:/ upload / attachments”至少需要一个名为“WEB-INF”的目录,其中包含“web.xml”。注意不要从上载Web应用程序提供对此目录和文件的写访问权限。使用此配置,您可以让tomcat为目录提供服务。
但是:将包含的web.xml配置为不将“* .jsp”作为jsp提供,否则tomcat不会只传递jsp文件而是执行它们。想象一下有人用<%System.exit(0)上传“index.jsp”; %或更多恶意内容。
One additional thought: You don't need the extra crosscontext="true"
. This would imply that the webapplication that you deploy just to serve your files has access to other webapplications, e.g. is able to manage them or access their private data. Usually you don't need that at all, in the case of your question you definitely don't want that.
另外一个想法:你不需要额外的crosscontext =“true”。这意味着您为部署文件而部署的Web应用程序可以访问其他Web应用程序,例如能够管理它们或访问他们的私人数据。通常你根本不需要它,在你的问题的情况下,你绝对不希望这样。
#3
2
See the initial part of my newer question for ways to do this by editing the context.xml file How do I add aliases to a Servlet Context in java?. According to several people now, it is no longer necessary (2012: Tomcat 6 or 7) to use Apache for performance reasons over Tomcat for serving static content.
通过编辑context.xml文件,查看我的新问题的初始部分,了解如何执行此操作如何在java中向Servlet上下文添加别名?根据现在的几个人的说法,不再需要(2012:Tomcat 6或7)因为性能原因而使用Apache而不是Tomcat来提供静态内容。
#1
9
I spent a lot more time researching this and found a solution that solves the random deletion of the context files. I found this excerpt on Apache's website under the host configuration section:
我花了很多时间研究这个,并找到了一个解决方案来解决上下文文件的随机删除问题。我在Apache的网站上在主机配置部分找到了这个摘录:
You can nest one or more Context elements inside this Host element, each representing a different web application associated with this virtual host.
您可以在此Host元素中嵌套一个或多个Context元素,每个元素表示与此虚拟主机关联的其他Web应用程序。
The virtual hosts are stored in the server.xml file located at CATALINA_HOME\conf. Tomcat comes configured with localhost as the default host. So, if we add the contents of attachments.xml from the first post, we get the following:
虚拟主机存储在位于CATALINA_HOME \ conf的server.xml文件中。 Tomcat配置了localhost作为默认主机。因此,如果我们从第一篇文章添加attachments.xml的内容,我们会得到以下内容:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Context path="/attachments"
docBase="e:\uploads\attachments"
reloadable="true"
crossContext="true" />
</Host>
This is as close as one can get to defining aliases similar to Apache's HTTP server, I think.
我认为这与定义类似于Apache的HTTP服务器的别名非常接近。
#2
7
There are multiple options.
有多种选择。
- Use Apache as frontend, delegating to tomcat by mod_jk or mod_proxy
- Provide a download servlet in your own application, serving the requested file
- Make the directory that you want tomcat to deliver a web application
使用Apache作为前端,通过mod_jk或mod_proxy委托给tomcat
在您自己的应用程序中提供下载servlet,为所请求的文件提供服务
创建您希望tomcat提供Web应用程序的目录
each has some drawbacks and some advantages. I strongly prefer the first solution for multiple reasons:
每个都有一些缺点和一些优点。出于多种原因,我非常喜欢第一种解决方案:
- My main reasons apply to unixoid systems, which you are obviously not talking about: Only root can bind ports lower than 1024, e.g. 80. Therefor tomcat would need to run as root (I know that there are mechanics to allow users to bind to low ports, but I've never gotten to use them). Apache is usually started as root but drops these privileges as soon as port 80 is bound.
- Apache is said to be a lot better in serving static resources than tomcat (I've never measured it, but find it hard to believe the contrary)
- You obviously know how to create aliases in apache - it would be trivial to do so.
我的主要原因适用于unixoid系统,你显然没有谈到:只有root可以绑定低于1024的端口,例如80.因此tomcat需要以root身份运行(我知道有一些机制允许用户绑定到低端口,但我从来没有使用它们)。 Apache通常以root身份启动,但只要端口80绑定就会丢弃这些权限。
据说Apache在提供静态资源方面要比tomcat好很多(我从未测量过它,但很难相信相反)
你显然知道如何在apache中创建别名 - 这样做很简单。
About the download servlet:
关于下载servlet:
This way you'd have a servlet serving your static resources, which you might bind to the urls "/download/*" (e.g. in the application that also handles file uploads) You'd gain:
这样你就有了一个为你的静态资源提供服务的servlet,你可以将它绑定到URL“/ download / *”(例如在同样处理文件上传的应用程序中)你将获得:
- You need to configure the directory where your files are stored only once
- If you need you might easily implement permission checks (e.g. login required for downloading)
- You need to deploy only one completely selfcontained application.
- The download servlet is trivial - find the file, set it's name and filetype in the output stream and stream it byte by byte, then close the output stream (be sure to handle attacking file names like "/download/../../../../etc/passwd" or "/download/C:/WINDOWS/someimportantfile.xxx"), e.g. by using the java.io.File constructor that gets the base directory as a separate parameter.
您只需配置一次存储文件的目录
如果需要,您可以轻松实施权限检查(例如下载所需的登录)
您只需部署一个完全自包含的应用程序。
下载servlet是微不足道的 - 找到文件,在输出流中设置它的名称和文件类型并逐字节流,然后关闭输出流(确保处理攻击文件名,如“/download/../../ ../../etc/passwd“或”/download/C:/WINDOWS/someimportantfile.xxx“),例如通过使用java.io.File构造函数将获取基目录作为单独的参数。
The third option has some severe drawbacks and opens you for attacks if you don't take special care of them:
第三种选择有一些严重的缺点,如果您不特别照顾它们,可以打开攻击:
- Tomcat does not serve directories, but webapps. Therefor "E:/upload/attachments" would need at least a directory named "WEB-INF", containing "web.xml". Take care to not provide write access to this directory and file from the uploading web application. With this provision you might let tomcat serve the directory.
- However: Configure the contained web.xml to not serve "*.jsp" as a jsp, otherwise tomcat would not just deliver jsp files but execute them. Imagine someone uploading "index.jsp" with
<% System.exit(0); %>
or more malicious content.
Tomcat不提供目录,而是提供webapps。因此,“E:/ upload / attachments”至少需要一个名为“WEB-INF”的目录,其中包含“web.xml”。注意不要从上载Web应用程序提供对此目录和文件的写访问权限。使用此配置,您可以让tomcat为目录提供服务。
但是:将包含的web.xml配置为不将“* .jsp”作为jsp提供,否则tomcat不会只传递jsp文件而是执行它们。想象一下有人用<%System.exit(0)上传“index.jsp”; %或更多恶意内容。
One additional thought: You don't need the extra crosscontext="true"
. This would imply that the webapplication that you deploy just to serve your files has access to other webapplications, e.g. is able to manage them or access their private data. Usually you don't need that at all, in the case of your question you definitely don't want that.
另外一个想法:你不需要额外的crosscontext =“true”。这意味着您为部署文件而部署的Web应用程序可以访问其他Web应用程序,例如能够管理它们或访问他们的私人数据。通常你根本不需要它,在你的问题的情况下,你绝对不希望这样。
#3
2
See the initial part of my newer question for ways to do this by editing the context.xml file How do I add aliases to a Servlet Context in java?. According to several people now, it is no longer necessary (2012: Tomcat 6 or 7) to use Apache for performance reasons over Tomcat for serving static content.
通过编辑context.xml文件,查看我的新问题的初始部分,了解如何执行此操作如何在java中向Servlet上下文添加别名?根据现在的几个人的说法,不再需要(2012:Tomcat 6或7)因为性能原因而使用Apache而不是Tomcat来提供静态内容。