好,朋友们.
在努力解决这个问题后,我想我终于找到了解决问题的方法.首先,看起来问题实际上分解为两个独立的任务.其中一个是保护对某些资源的访问,另一个是从上下文之外的文件夹中提供资源.
第一项任务是微不足道的,可以通过编写一个挂在"/"上的简单过滤器来解决.
第二项任务不那么简单,但幸运的是,也可以解决.Tomcat使用javax.naming.directory.DirContext的实现来加载给定Web应用程序的所有资源,包括类文件.它还允许您提供此接口的自定义实现,并在context.xml文件中对其进行配置.默认实现是org.apache.naming.resources.FileDirContext.详细信息:http://tomcat.apache.org/tomcat-6.0-doc/config/resources.html
我通过简单地扩展FileDirContext创建了我自己的DirContext实现.幸运的是,有一种方法必须被覆盖才能"挂钩"文件发现.该方法称为file().
我在这里发布我的测试代码.它远非完美,并没有考虑重命名文件等极端情况,但我不认为在正常运行的服务器下需要这些.
这段代码的基本思想是检查路径是否以"虚拟目录"前缀开头,如果是 - 在文件系统的其他位置搜索文件(我知道那里有一些重复的代码,但我希望你不是如果你想使用它,懒惰去除它:-).自动调用setVirtualName和setVirtualBase以注入配置参数.
/**
* TODO: add javadocs
*
* @author Juriy Bura
*/
public class VirtualFolderDirContext extends FileDirContext {
private String virtualName;
private String realName;
private File virtualBase;
private String absoluteVirtualBase;
public VirtualFolderDirContext() {
super();
}
public VirtualFolderDirContext(Hashtable env) {
super(env);
}
public void setVirtualName(String path) {
virtualName = path;
}
public void setVirtualBase(String base) {
this.realName = base;
virtualBase = new File(realName);
try {
virtualBase = virtualBase.getCanonicalFile();
} catch (IOException e) {
// Ignore
}
this.absoluteVirtualBase = virtualBase.getAbsolutePath();
}
protected File file(String name) {
File file = null;
boolean virtualFile = name.startsWith(virtualName + "/");
if (virtualFile) {
file = new File(virtualBase, name.substring(virtualName.length()));
} else {
file = new File(base, name);
}
if (file.exists() && file.canRead()) {
if (allowLinking)
return file;
// Check that this file belongs to our root path
String canPath = null;
try {
canPath = file.getCanonicalPath();
} catch (IOException e) {
}
if (canPath == null)
return null;
// Check to see if going outside of the web application root
if (!canPath.startsWith(absoluteBase) && !canPath.startsWith(absoluteVirtualBase)) {
return null;
}
// Case sensitivity check
if (caseSensitive) {
String fileAbsPath = file.getAbsolutePath();
if (fileAbsPath.endsWith("."))
fileAbsPath = fileAbsPath + "/";
String absPath = normalize(fileAbsPath);
if (canPath != null)
canPath = normalize(canPath);
if (virtualFile) {
if ((absoluteVirtualBase.length() < absPath.length())
&& (absoluteVirtualBase.length() < canPath.length())) {
absPath = absPath.substring(absoluteVirtualBase.length() + 1);
if ((canPath == null) || (absPath == null))
return null;
if (absPath.equals(""))
absPath = "/";
canPath = canPath.substring(absoluteVirtualBase.length() + 1);
if (canPath.equals(""))
canPath = "/";
if (!canPath.equals(absPath))
return null;
}
} else {
if ((absoluteBase.length() < absPath.length())
&& (absoluteBase.length() < canPath.length())) {
absPath = absPath.substring(absoluteBase.length() + 1);
if ((canPath == null) || (absPath == null))
return null;
if (absPath.equals(""))
absPath = "/";
canPath = canPath.substring(absoluteBase.length() + 1);
if (canPath.equals(""))
canPath = "/";
if (!canPath.equals(absPath))
return null;
}
}
}
} else {
return null;
}
return file;
}
}
Run Code Online (Sandbox Code Playgroud)
在你拥有这个类之后,你必须将它jar并将它放入Tomcat lib文件夹中.由于显而易见的原因,它不能与war文件一起使用.在context.xml中,您应该添加如下配置行:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="true" antiJARLocking="true">
<Resources
className="com.juriy.tomcat.virtualdir.VirtualFolderDirContext"
virtualName="/upload"
virtualBase="c:/temp/up">
</Resources>
...
...
Run Code Online (Sandbox Code Playgroud)
现在,只要用户要求/ upload /它将被解析为c:\ temp.使用此技术,您可以从几乎任何位置实现加载资源:http,共享文件夹,数据库,甚至版本控制系统.所以这很酷.
PS我已经杀了整整一天让这一切都在一起工作所以如果你喜欢答案,请不要犹豫,给我你的投票:-))
干杯
Juriy
| 归档时间: |
|
| 查看次数: |
1326 次 |
| 最近记录: |