在Tomcat 7以前的版本中使用Invoker Servlet提供的映射机制带来的安全问题包括:
1、应用的类名直接暴露在路径中,这是显而易见的安全问题。
2、缺乏配置信息造成类调用的混乱。在有同名类的时候,服务器无法确定调用这个类还是那个类。而在web.xml中每个应用都有明确的描述和路径映射,对应用的运行有明确的线路,且更有利于应用的维护。
3、存在后门的危险。一个被映射在不同路径的类有可能利用Invoker机制通过类名被访问到,这样就绕过了系统的安全机制。
4、还是存在后门的危险。应用中经常会在公共领域使用第三方类库,如果这个第三方类库中包含有漏洞,那么它就有可能通过Invoker机制被激活。
Tomcat 7实现的Servlet 3.0标准不再支持这个Invoker Servlet类,貌似给应用的原型开发阶段带来不便,但新标准引入了更加便捷和安全的解决方法:一、使用应用描述文件web.xml描述你的应用。
为每个一个类,在web.xml中添加描述信息,虽然这是一个繁琐的过程,尤其对于开发阶段来说,但这是最安全和规范的做法。例如一个简单的测试应用HelloServlet,其部分源码如下:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet {
/* snip... */
}
我们可以在web.xml中为其进行如下配置,使其地址映射在/sayHello
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="false" >
<display-name>Test Servlet</display-name>
<description>
Test Servlet
</description>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/sayHello</url-pattern>
</servlet-mapping>
</web-app>
二、在应用的源码中使用注解进行应用的自描述。
Tomcat 7实现的Servlet 3.0标准引入一个新的特性,叫annotaion,这里且称为注解,它包括有多种注解,具体可参见官方的文档,其中有一个注解@WebServlet。在主类的声明前插入这个注解可以实现对当前类的配置,服务器会根据这个信息正确调用当前类。这样就省去了配置web.xml,极大得方便了开发阶段应用的配置过程。@WebServlet有很多选项可以进行应用配置,最简单的例子就是给出路径映射@WebServlet(“/path”),更复杂的情况是给出应用名,甚至为一个应用给出多个替代路径@WebServlet(name=”TestServlet”, urlPatterns={“/path”, “/alt”})。
同样为上面的简单测试例子,只把类名改为HelloServletAgain,这次用注解实现应用配置,并映射了两个地址,而web.xml不需要进行任何配置。注意两点:一是要引入包javax.servlet.annotation.*,二是web.xml中web-app项的metadata-complete属性必须设为false。部分源码如下:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
/** Simple servlet used to test server. **/
@WebServlet(name=”HelloServletAgain”, urlPatterns={“/sayHello”, “/sayHelloAlt”})
public class HelloServletAgain extends HttpServlet {
/* snip... */
}
通过访问/sayHello或/sayHelloAlt,就可以访问这个应用。