我使用的是为 Ubuntu Karmic 打包的 Tomcat 6.0.24。Ubuntu 的 Tomcat 包的默认安全策略非常严格,但看起来很简单。在/var/lib/tomcat6/conf/policy.d
中,有多种建立默认策略的文件。
开头值得注意:
- 我根本没有更改股票 tomcat 安装 - 没有新的 jars 进入它的公共 lib 目录,没有
server.xml
更改等。将 .war 文件放在webapps
目录中是唯一的部署操作。 - 在此默认策略下,我正在部署的 Web 应用程序因数千次访问被拒绝而失败(由于
-Djava.security.debug="access,stack,failure"
系统属性而向日志报告)。 - 完全关闭安全管理器不会导致任何错误,并且应用程序功能正常
我想做的是将特定于应用程序的安全策略文件添加到policy.d
目录中,这似乎是推荐的做法。我将此添加到policy.d/100myapp.policy
(作为起点——我希望最终将授予的权限缩减为仅应用程序实际需要的权限):
grant codeBase "file:${catalina.base}/webapps/ROOT.war" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/lib/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/classes/-" {
permission java.security.AllPermission;
};
请注意试图找到正确codeBase
声明的挣扎。我认为这可能是我的根本问题。
无论如何,上面的(实际上只有前两个授权似乎有任何效果)几乎可以工作:成千上万的访问拒绝已经消失,我只剩下一个。相关堆栈跟踪:
java.security.AccessControlException: access denied (java.io.FilePermission /var/lib/tomcat6/webapps/ROOT/WEB-INF/classes/com/foo/some-file-here.txt read)
java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
java.security.AccessController.checkPermission(AccessController.java:546)
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
java.lang.SecurityManager.checkRead(SecurityManager.java:871)
java.io.File.exists(File.java:731)
org.apache.naming.resources.FileDirContext.file(FileDirContext.java:785)
org.apache.naming.resources.FileDirContext.lookup(FileDirContext.java:206)
org.apache.naming.resources.ProxyDirContext.lookup(ProxyDirContext.java:299)
org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:1937)
org.apache.catalina.loader.WebappClassLoader.findResource(WebappClassLoader.java:973)
org.apache.catalina.loader.WebappClassLoader.getResource(WebappClassLoader.java:1108)
java.lang.ClassLoader.getResource(ClassLoader.java:973)
我非常确信触发拒绝的实际文件是无关紧要的——它只是我们检查可选配置参数的一些属性文件。有趣的是:
- 在这种情况下不存在
- 文件不存在的事实最终会引发安全异常,而不是
java.io.File.exists()
简单地返回 false (尽管我认为这只是读取权限的语义问题)。
另一个解决方法(除了在 tomcat 中禁用安全管理器之外)是向我的策略文件添加开放式权限:
grant {
permission java.security.AllPermission;
};
我认为这在功能上等同于关闭安全管理器。
我想我一定是codeBase
在我的赠款中得到了微妙的错误,但我现在没有看到它。