Java 的 SecurityManager 能让 Web 浏览器在它自身的沙盒中运行小型应用(applet),从而具有防止不可信代码访问本地文件系统的文件以及防止其连接到主机,而不是加载该应用的位置,等等。如同 SecurityManager 能防止不可信的小型应用在你的浏览器上运行,运行 Tomcat 时,使用 SecurityManager 也能保护服务器,使其免受木马型的 applet、JSP、JSP Bean 以及标签库的侵害,甚至也可以防止由于无意中的疏忽所造成的问题。
假设网站有一位经授权可发布 JSP 的用户,他在无意中将下面这些代码加入了 JSP 中:
<% System.exit(1); %>
每当 Tomcat 执行这个 JSP 文件时,Tomcat 都会退出。Java 的 SecurityManager 构成了系统管理员保证服务器安全可靠的另一道防线。
警告:使用 Tomcat 代码库时会执行一个安全审核。大多数关键包已受到保护,新的安全包保护机制已经实施。然而,在允许不可信用户发布 Web 应用、JSP、servlet、bean 或标签库之前,你仍要反复确定自己配置的 SecurityManager 是否满足了要求。但不管怎么说,利用 SecurityManager 来运行 Tomcat 肯定比没有它好得多
权限类用于定义 Tomcat 加载的类所具有的权限。标准 JDK 中包含了很多标准权限类,你还可以针对自己的 Web 应用自定义权限类。Tomcat 支持这两种技术。
关于适用于 Tomcat 的标准系统 SecurityManager 权限类,以下仅是一个简短的总结。
java.home
。
exit()
和 exec()
。 另外也控制包的访问/定义。
Tomcat 使用了一个自定义权限类 org.apache.naming.JndiPermission。该权限能够控制对 JNDI 命名的基于文件的资源的可读访问。权限名就是 JNDI 名,无任何行为。后面的 *
可以用来在授权时进行模糊匹配。比如,可以在策略文件中加入以下内容:
permission org.apache.naming.JndiPermission "jndi://localhost/examples/*";
从而为每个部署的 Web 应用动态生成这样的权限项,允许它们读取自己的静态资源,而不允许读取其他的文件(除非显式地赋予这些文件权限)。
另外,Tomcat 还能动态生成下面这样的文件权限。
permission java.io.FilePermission "** your application context**", "read";
permission java.io.FilePermission
"** application working directory**", "read,write";
permission java.io.FilePermission
"** application working directory**/-", "read,write,delete";
*application working directory 是部署应用所用的文件夹或 WAR 文件。 application working directory 是应 Servlet 规范需要而提供给应用的暂时性目录。
Java SecurityManager 所实现的安全策略配置在 $CATALINA_BASE/conf/catalina.policy
文件中。该文件完全替代了 JDK 系统目录中提供的 java.policy
文件。既可以手动编辑 catalina.policy
文件,也可以使用Java 1.2 或以后版本附带的 policytool 应用。
catalina.policy
文件中的项使用标准的 java.policy
文件格式,如下所示:
// 策略文件项范例
grant [signedBy <signer>,] [codeBase <code source>] {
permission <class> [<name> [, <action list>]];
};
signedBy 和 codeBase 两项在授予权限时是可选项。注释行以 //
开始,在当前行结束。codeBase
以 URL 的形式。对于文件 URL,可以使用 ${java.home}
与 ${catalina.home}
属性(这些属性代表的是使用JAVA_HOME
、CATALINA_HOME
和 CATALINA_BASE
环境变量为这些属性定义的目录路径)。
一旦配置好了用于 SecurityManager 的 catalina.policy
文件,就可以使用 -security
选项启动带有 SecurityManager 的 Tomcat。
$CATALINA_HOME/bin/catalina.sh start -security (Unix)
%CATALINA_HOME%\bin\catalina start -security (Windows)
从 Tomcat 5 开始,可以通过配置保护 Tomcat 内部包,使其免于被定义与访问。
警告:假如去除默认的包保护,可能会造成安全漏洞。
默认的 $CATALINA_BASE/conf/catalina.properties
文件如下所示:
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,
org.apache.jasper.
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageDefinition unless the
# corresponding RuntimePermission ("defineClassInPackage."+package) has
# been granted.
#
# by default, no packages are restricted for definition, and none of
# the class loaders supplied with the JDK call checkPackageDefinition.
#
package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,
org.apache.tomcat.,org.apache.jasper.
一旦为 SecurityManager 配置了 catalina.properties
文件 ,记得重启 Tomcat。
假如应用执行一个由于缺乏所需权限而被禁止的操作,当 SecurityManager 侦测到这种违规时,就会抛出AccessControLException
或 SecurityException
异常。虽然调试缺失的权限是很有难度的,但还是有一个办法,那就是将在执行中制定的所有安全决策的调试输出打开,这需要在启动 Tomcat 之前设置一个系统属性。最简单的方法就是通过 CATALINA_OPTS
环境变量来实现,命令如下所示:
export CATALINA_OPTS=-Djava.security.debug=all (Unix)
set CATALINA_OPTS=-Djava.security.debug=all (Windows)
记住,一定要在启动 Tomcat 之前去做。
警告:这将生成很多兆的输出内容!但是,它能通过搜索关键字 FAILED
来锁定问题所在位置,确定需要检查的权限。此外,查阅 Java 安全文档可了解更多的可设置选项。