`
kalogen
  • 浏览: 880251 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Tomcat 7的七大特性:新特性与增强功能

阅读更多

Tomcat 7 在加强原有功能的同时也增加了一些新特性。有些文章列举了Tomcat 7的新特性,但大多数都没有对它们进行详细地解释、评价并给出可执行的示例。除了列举出新特性,这篇文章还对Tomcat 7的七个最值得注意的特性与增强部分进行分类、评定以及演示可执行代码以使你能够对每个特性/加强有个更好的理解。

我将下面列举的这些分类为“Tomcat 7 新特色:创新性改变”和“Tomcat 7 加强:进化性改变”:

Tomcat 7 新特性:创新性改变

  1. 使用随机数令牌(nonce)防止跨站请求伪造(cross-site request forgery—CSRF)攻击
  2. 验证时改变 jsessionid 以防止固定会话攻击
  3. 内存泄露检测及预防
  4. 使用别名在war文件外存储静态内容

Tomcat 7 加强:进化性改变

  1. Servlet 3.0, JSP 2.2 和 JSP-EL 2.2 支持
  2. 将Tomcat嵌入你的应用,例如JBoss中,会更加简单
  3. 异步日志

据 Mark Thomas(Tomcat 7的发布负责人及提交者)所言,Tomcat 7最引人注目的三个特点 是 Servlet 3.0, 内存泄露预防与检测,和提高的安全性。

随附的 Tomcat 7 演示 文件包含了一个Eclipse攻城和一个Ant创建文件,你可以用其创建一个war包。Eclipse工程中的示例代码描述了Tomcat 7的两个新特性。

这篇文章的其余部分将详细阐述这七个最值得的关注新特性和增强功能。&

Tomcat 7 新特性: 创新型改变

这个部分讨论先前划定的四个新特性。

1. 使用 随机数令牌(nonce)来阻止跨站请求伪造(CSRF)攻击

Webopedia(在线计算机字典)这样定义跨站请求伪造(CSRF):“一种恶意攻击基于web的应用程序。一次典型的恶意攻击将迫使用户在登录可信任站点的时候执行一些不必要的操作。”对CSRF更形象的定义是 session riding(子乌注:好吧,这个“更形象”的定义我实在看不懂……可参看session riding)。

阻止CSRF的典型做法就是使用随机数令牌,在wikipedia中对它的定义是“一个 用于认证协议的随机或伪随机数,以确保老的通信不会在重播攻击中被复用。”

Tomcat 7 有一个servlet过滤器,用于在每次提交请求之后在用户的会话中保存一个随机数令牌。这个随机数令牌必须添加到后续的每一个请求中做为一个请求参数。这个servlet过滤器会检测这个请求参数是否与存储于用户会话中的随机数令牌一致。如果一致,请求就只能是来自指定站点。如果不同,这个请求会被认为是来自不同的站点并被拒绝。

servlet过滤器非常简单。这里有一个相关源码(来自 Apache Software Foundation CsrfPreventionFilter 文档)的片断:

Language:  Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class CsrfPreventionFilter extends FilterBase {
...
...
...
public void doFilter(ServletRequest request, ServletResponse response,
 FilterChain chain) throws IOException, ServletException {
...
...
...
 String previousNonce = req.getParameter(Constants.CSRF_NONCE_REQUEST_PARAM);
 String expectedNonce = (String) req.getSession(true).getAttribute(Constants.CSRF_NONCE_SESSION_ATTR_NAME);
 
 if (expectedNonce != null && !expectedNonce.equals(previousNonce)) {
 res.sendError(HttpServletResponse.SC_FORBIDDEN);
 return;
 }
 
 String newNonce = generateNonce();
 
 req.getSession(true).setAttribute(Constants.CSRF_NONCE_SESSION_ATTR_NAME, newNonce);
...
...
...

所以每个URL都必须包含一个从用户会话中获取的随机数令牌。这是一个使用JSP-EL的示例::

Before:

Language:  XML
1
2
3
4
<c:url var="url" value="/show" >
 <c:param name="id" value="0" />
</c:url>
<a href="${show}" >Show</a>

After:

Language:  XML
<c:url var="url" value="/show">
 <c:param name="id" value="0" />
 <c:param name="org.apache.catalina.filters.CSRF_NONCE" value="${session.org.apache.catalina.filters.CSRF_NONCE}" />
</c:url>
<a href="${show}">Show</a>

拿附件 Tomcat 7 示例的样本工程作为示例。web.xml 文件中配置了过滤器,随着这个过滤器的到位,所有访问 http://localhost:8080/tomcat7demo/csrf/ URL的请求如果没有将随机数令牌作为请求参数都会返回403错误 (“访问被拒绝”)。

一个非法请求(如在垃圾邮件中)不可能拥有随机数令牌。因此,一个session riding攻击无法奏效。即使如果用户点击了一个恶意链接或提交了一个恶意表单,请求也会被拒绝,因为没有随机数令牌。随机数令牌目前只会存在于web应用返回的web页面中。

这种方法的缺陷是所有的URL链接都必须带着这个随机数令牌做请求参数。

2. 验证时改变 jsessionid 以防止固定会话攻击

一个固定会话攻击发生时可能像这样:

  1. 一个恶意用户访问一个站点后,浏览器会有一个cookie存放jsessionid————即使用户没有登录。然后他伪造一个带有jsessionid的URL并将它发送给受害者 (如 http://example.com/login?JESSIONID=qwerty).
  2. 受害者点击带有该jsessionid的URL并被提示输入验证信息。受害者登录。
  3. 恶意用户现在可以使用带着该jsessionid的URL来以受害者的身份登录网站。

攻击者将一个jsessionid加入URL中或通过一个恶意表单将其提交到http头中是很常见的。(如果需要一个固定会话攻击的完整描述,参看来自Acros Security的白皮书 “Session Fixation Vulnerability in Web-based Applications“)。

Tomcat团队实现的解决方案是打个补丁:认证后改变jsessionid。这个补丁已经在Tomcat 7中起效并且向后兼容至Tomcat 5和6,只是有一些区别。

Mark Thomas关于Tomcat 7下这个补丁的效果的描述:

  • 默认情况下由于会话ID在验证结束后会发生改变,Tomcat并不容易受到攻击。
  • 如果默认配置被用户修改(如,因为程序不能处理不断变化的会话ID),那可以通过禁用URL会话跟踪(Servlet 3的新特性)来降低风险。

在Tomcat 5和6中,这个补丁的效果:

  • 通过启用Tomcat在验证时改变会话ID可以避免固定会话攻击(如果足够的支持,这是默认启用的)。
  • 如果应用程序无法处理一个不断变化的会话ID,那可以通过写一个自定义过滤器检测request.isRequestedSessionIdFromURL()并做出相应回应(例如拒绝请求)来降低风险。

上述变动会在幕后悄悄地进行,开发者无须做任何事情。用户会话(jsessionid)在登录后发生改变。这将会彻底杜绝固定会话攻击。

3. 内存泄露检测与预防

程序员在他们的开发环境中部署更新版本的web应用程序时经常会遇到错误Permgen space: OutOfMemoryError。这是由内存泄露导致的。上一次部署的类并没有被完全地垃圾收集。开发人员一般通过增加内存PermGen的大小和重启Tomcat来解决这个问题。

Tomcat 7推出了一个新特性来解决由于PermGen空间中移除引用的对象没有被垃圾收集导致的内存泄露。该功能是用于程序员部署应用到开发环境的。在开发环境中,为了节约时间程序员会试着在不重启Tomcat的情况下重新部署新war文件。在产品部署时,比较好的方式是停止Tomcat,清空work目录,部署新应用。

但这个内存泄露检测与预防功能并不完美。依然存在Tomcat无法处理内存泄露并且也无法检测的情况。所以对于产品系统来说,最好还是停止Tomcat,清空work目录以及旧的web应用,然后部署新web应用再重启Tomcat。

Mark Thomas解释了哪些应用或者库代码可能触发这个情势:

  • JDBC驱动器注册
  • 一些日志框架
  • 保存对象到ThreadLocals并且不移除他们
  • 启动线程而不停止他们

还有很多地方存在使用标准Java Api可能导致类似的问题。他们包括:

  • 使用javax.imageio API (Google Web Toolkit会触发它)
  • 使用java.beans.Introspector.flushCaches() (Tomcat使用这个来防止由于缓存导致的内存泄露。)
  • 使用XML解析(根本原因未知,和JRE中的bug有关)
  • 使用RMI (有点讽刺的是导致泄露的原因和垃圾收集器有关)
  • 在JAR文件中读取资源

4. 使用别名在War文件外存储静态内容

一个web应用可能需要静态资源,如CSS,JavaScript,以及视频和图像文件。这些通常是包含在包含在绑定的war文件中。这会增加war文件的大小并会导致静态资源的冗余。对这个的替代方案是使用Apache HTTP服务器来存放静态内容。这是从Apache httpd.conf中显示别名的相关片断:

Language:  Apache configuration
<Directory "/home/avneet/temp/static">
Order allow,deny
Allow from all
</Directory>
Alias /static "/home/avneet/temp/static"

上述的Apache指令将让目录/home/avneet/temp/static下的内容在URLhttp://localhost/static/下可见。

Tomcat 7 现在提供了一个替换方法。Tomcat 7允许context元素上有一个新的属性aliases。这个新属性可以指向一个静态的资源。你现在可以通过Classloader.getResourceAsStream('/static/...')来访问它或者在给它设一个link值,让Tomcat解析其绝对路径。下面是一个context.xml的示例:

Language:  XML
<?xml version="1.0" encoding="UTF-8"?>
<context path="/tomcat7demo" aliases="/static=/home/avneet/temp/static">
...
...
...
</Context>

假设目录 /home/avneet/temp/static 包含图片 bg.png 而且 context.xml 文件已经编辑为如上内容。

如果 war 文件部署为 tomcat7demo, 你现在可以通过下面的三种方式访问这个映射的图片资源:

  1. 直接访问: http://localhost:8080/tomcat7demo/static/bg.png
  2. 在HTML页面中内嵌一个链接: < img src="/tomcat7demo/static/bg.png" / >
  3. 在Java代码中访问: ByteArrayInputStream bais = (ByteArrayInputStream)getServletContext().getResourceAsStream("/static/bg.png");(子乌注:我不太喜欢这种方式,这意味着将你的应用程序与Tomcat绑定,如果需要更换web容器的话,会是一个有些麻烦的事情。)

使用这个别名而非httpd.conf中Apache别名的优势在于该映射资源可以从一个servlet中访问,而且这个别名能够被用于不是以Apache做前端服务器的应用程序。

Tomcat 7 加强:进化性改变

这个部分将讨论前面定义的三个增强功能。

5. Servlet 3.0, JSP 2.2 和 JSP-EL 2.2 支持

Servlet 3.0增强的部分:

  • 能将添加注释的POJO作为servlet和(或)过滤器使用(不再需要web.xml)(子乌注:啊,我爱死这点了~~)
  • 可以在Web fragments中解析部署————Web fragments是只包含部分部署信息的XML文件。Servlet引擎根据这些Web fragments构造最终的web.xml。这个可以用来降低web.xml文件的复杂度。
    举例,struts.jarspring-mvc.jar可以有一个web-fragment.xml。这个保存于JAR中的web-fragment.xml会被自动检测到而struts/spring-mvc servlet和过滤器会被自动配置。
  • 异步处理Web请求(这个功能在Tomcat 6中已经生效不过现在在Servlet 3/Tomcat 7中成为了标准配置),用来建立跨web容器异步IO可移植的应用程序(子乌注:翻译的好拗口,原文:Web applications that use async I/O portable across Web containers)。它使用非锁定(non-blocking) I/O,而每个HTTP链接并不要求使用一个线程。更少的线程服务于更多的HTTP链接。这尤其利于那些触发运行长时间进程然后返回一个结果的HTTP请求(例如,报表生成,慢速数据库,Web service调用等)。
  • 安全相关的改变————兼容Servlet 3.0的容器现在可以使用SSL和会话跟踪,而不是cookies和URL重写。

DevX 发布了一个很赞的关于 Servlet 3.0 变化的解释。

6. 更容易将Tomcat内嵌入你的应用程序

Tomcat现在可以内嵌进一个应用程序,而且它可以通过编程进行配置及启动。CATALINA_HOME/conf/server.xml中的大部分配置可以通过编程完成。 在TOmcat 7之前,Tomcat 6提供了一个Embedd类,提供了便利的方法来配置Tomcat。这个类现在已经不推荐使用。新的类Tomcat使用了一些配置单元的默认值并提供了更简单易用的方法来内嵌Tomcat。

这里是一些来自CATALINA_HOME/conf/server.xml的Tomcat配置单元的常用结构和一些相关属性:

Language:  XML
<Server>
 <Service>
 <Connector port="8080">
 <Engine>
 <Host appBase="/home/avneet/work/tomcat7demo/dist" />
 </Engine>
 </Connector>
 </Service>
</Server>

为了程序化的配置这些,你必须建立所有上述对象并配置他们,下面是一份完成这个工作的Java代码:

Language:  Java
final String CATALINA_HOME = "/home/avneet/work/temp/tomcat7demo/";
 Tomcat tomcat = new Tomcat();
 tomcat.setBaseDir( CATALINA_HOME );
 tomcat.setPort( 8080 );
 tomcat.addWebapp("/tomcat7demo", CATALINA_HOME + "/webapps/tomcat7demo.war");
 tomcat.start();
 System.out.println("Started tomcat");
 tomcat.getServer().await(); //保持Tomcat一直运行,直到被关闭
 //Webapp tomcat7demo accessible at http://localhost:8080/tomcat7demo/

7. 异步日志

Tomcat 7 现在包含了一个异步文件日志记录器(AsyncFileHandler). AsyncFileHandler 扩展了 FileHandler 并能替换 FileHandler。要使用 AsyncFileHandler,只要简单地将CATALINA_HOME/conf/logging.properties文件中所有出现的FileHandler替换为AsyncFileHandler。应用程序必须使用 java.util.Logging; 因为Log4j还不支持异步日志记录。

当一个条日志信息发送给AsyncFileHandler时,日志信息会添加到一个 queue(java.util.concurrent.LinkedBlockingDeque),然后这个调用记录信息的方法会立刻返回,无须等待I/O到磁盘。当AsyncFileHandler被class loader加载时一个独立的线程会启动。这个线程从队列中读取日志信息并将其写入到磁盘。

这个方法的优势在于当I/O输出磁盘很慢的时候(例如,日志文件存放在远程驱动器上),日志记录不会拖慢请求处理。

AsyncFileHandler与队列之间采用生产者/消费者的关系来处理日志信息储存。标准的队列大小为10000。当溢出的时候,默认的行为是丢掉最后一条信息。默认大小和溢出行为都可以通过修改启动系统属性来配置。

关于 Tomcat 7 演示程序

附件 Tomcat 7 Demo web应用程序有两个servlet。一个servlet演示如何使用随机数令牌来防止CSRF,第二个演示了别名的用法。更新 web/META-INF/context.xml 文件,指向images目录的绝对路径 (如 ./images).

使用build.xml来编译war文件,并将其部署到Tomcat 7上。使用下列两个URL来查看CSRF过滤以及alias使用:

  • http://localhost:8080/tomcat7demo/csrf/
  • http://localhost:8080/tomcat7demo/alias/

总结

Tomcat团队介绍了Tomcat 7中的一些变化,包括了新的特性和对现有功能的强化。当这篇文章写下的时候这些变化还没有时间在生产系统中测试(最新的稳定版是7.0.2), team introduced several changes in Tomcat 7 in terms of both new features and enhancements to existing features. The changes had not been tested in production systems at time of writing (the latest stable release was 7.0.2), 但只要6-12个月,他们将成为主流并让程序员们更容易地部署更安全、高质量的基于Java的web应用。

关于作者

Avneet Mangat拥有9年的Java/J2EE开发经验,目前是在伦敦工作的独立IT顾问。他拥有一个牛津大学的软件工程硕士学位,通过了(Sun-Certified Java Programmer)、SCWCD(Sun-Certified Web Component Developer)、SCEA(Sun-Certified Enterprise Architect)和ACFD(Adobe-certified Flash Designer)认证,以及Prince2认证(基金会)。他是开源工具DBBrowser的首席开发者。(子乌注:我一般不在这里写注释,不过……看到这位仁兄的认证,我觉得我过去的那么多年都活到狗身上去了……我不蛋定了>_<)

分享到:
评论

相关推荐

    Tomcat 7 的七大新特性

    以下是对Tomcat 7七大新特性的详细说明: 1. **改进的WebSocket支持**: Tomcat 7开始支持JavaScript API for WebSocket(JSR 356),为Web应用程序提供了低延迟、双向通信的能力。WebSocket允许创建持久连接,...

    tomcat7最新版本

    【标题】"Tomcat7最新版本"涉及到的是Apache Tomcat服务器的第七个主要版本,即7.0.26。Tomcat是一款广泛使用的开源Java Servlet容器,它实现了Java EE的Servlet和JavaServer Pages (JSP) 规范,用于部署和运行Java ...

    tomcat7 tomcat9 两个资源

    标题中的“tomcat7 tomcat9 两个资源”指的是Apache Tomcat服务器的第七个和第九个主要版本。Tomcat是一款开源的Java Servlet容器,主要用于部署和运行Java Web应用程序。这两个版本之间的差异在于功能的增强、性能...

    linux64_tomcat7

    Tomcat 7引入了许多新特性,如改进的JMX(Java Management Extensions)支持,增强了管理工具,提升了性能,并对Servlet 3.0、JSP 2.2和EL 2.2等规范进行了支持。这些更新使得Tomcat 7成为开发和部署现代Java Web...

    Tomcat7.x 64位系统

    - “Tomcat 7.x”:这是Tomcat的第七次重大更新,引入了许多新特性和改进,包括对Servlet 3.0、JSP 2.2和EL 2.2规范的支持,增强了安全管理,以及性能优化。 - “Tomcat7”:是Tomcat7.x的简称,通常用于指代这个...

    tomcat7,正常,可用,需要jdk1.6版本

    【标题】"Tomcat7, 正常, 可用, 需要JDK1.6版本" 暗示了我们讨论的核心是Apache Tomcat服务器的第七个主要版本,一个广泛使用的开源Java Servlet容器,它实现了Java EE的Web应用服务规范。此版本的Tomcat被认为稳定...

    服务器压缩包tomcat-7

    "Tomcat-7"是我们讨论的重点,这个版本是Tomcat服务器的第七个主要版本,发布于2013年,提供了许多新功能和改进,旨在提高性能、安全性和稳定性。 1. **Servlet 3.0支持**:Tomcat 7支持Servlet 3.0规范,带来了...

    tomcat7x64

    在这个版本中,Tomcat引入了多项改进和新功能,例如增强了安全性能,提升了性能,优化了内存使用,以及对Java EE 6标准的支持。 【压缩包子文件的文件名称列表】"apache-tomcat-7.0.52"表明我们拥有的是Apache ...

    JDK7+TOMCAT7.zip

    JDK7在Java SE(标准版)平台中引入了一系列新特性,旨在提高开发人员的生产力,简化代码编写,并增强应用程序性能。其中,最重要的新特性包括: 1. **多线程并行GC(G1垃圾收集器)**:G1垃圾收集器是一个用于...

    tomcat7_64bit

    标签"tomcat7"进一步强调了讨论的主题,即Tomcat的第七个主要版本。在这一版本中,Tomcat引入了许多改进和新特性,例如支持Java EE 6规范,包括Servlet 3.0、JSP 2.2和EL 2.2等。此外,它还增强了安全管理、线程池...

    apache-tomcat6and7

    Apache Tomcat 7则是Tomcat的第七个主要版本,它支持Java Servlet 3.0和JSP 2.2规范。这个版本带来了许多改进,包括对WebSocket的支持,这是一个在浏览器和服务器之间进行全双工通信的新标准。此外,Tomcat 7还引入...

    tomcat7 tomcat 6 xshell6.zip

    Tomcat 7和Tomcat 6是Tomcat的不同版本,每个版本都有其特定的功能特性和兼容性。xShell 6则是一个流行的SSH(Secure Shell)客户端工具,用于远程控制和管理Linux或Unix服务器,提供安全的命令行访问。 【Tomcat 7...

    Apache Tomcat 7 Essentials by Tanuj Khare.pdf

    - **兼容性**:Tomcat 7 完全支持 Servlet 3.0 规范,这包括对新特性如异步处理的支持。 - **性能提升**:相比之前的版本,Tomcat 7 在多个方面进行了性能优化,尤其是在处理高并发请求时表现更为出色。 - **安全性...

    tomcat 7.0

    这个版本,7.0.6,是Tomcat 7系列的一个特定发布,包含了性能改进、安全修复和其他增强功能。 一、Tomcat 7.0核心特性 1. 支持Servlet 3.0:Tomcat 7引入了Servlet 3.0规范,提供了诸如异步处理、过滤器链的优化、...

    tomcat7_win_64bit

    Tomcat 7是Tomcat服务器的第七个主要版本,它包含了众多新特性和改进,例如对Java EE 6 Web Profile的支持,这使得开发者可以在不依赖完整的Java EE应用服务器的情况下,开发和部署符合规范的Web应用程序。...

    Tomcat7.0和8.0版本

    Tomcat 7.0是Apache Tomcat的第七个主要版本,它引入了许多增强功能和改进。7.0.40是这个版本的一个稳定更新,提供了对Java EE 6的支持,包括Servlet 3.0、JSP 2.2和EL 2.2标准。以下是一些关键特性: 1. **Servlet...

    Tomcat7和8合集.zip

    Tomcat 7是Apache软件基金会的Tomcat服务器的第七个主要版本。这个版本支持Java EE 6规范,包括Servlet 3.0、JSP 2.2和EL 2.2。以下是一些关键特性: 1. **Servlet 3.0**:引入了异步处理能力,允许Servlet在不阻塞...

    Tomcat7.0.39官方安装包

    2. **版本7.0.x**:在Tomcat的历史版本中,7.0.x系列引入了许多新特性,如Servlet 3.0、JSP 2.2、EL 2.2等规范的支持,增强了性能和安全性。 3. **39次小更新**:每个小版本的更新通常包含错误修复、安全改进和功能...

    tomcat 7.0.59

    Tomcat 7引入了许多新特性,比如支持Servlet 3.0和JSP 2.2标准,增强了对WebSocket的支持,以及改进了管理工具和部署流程。 【压缩包子文件的文件名称列表】"apache-tomcat-7.0.59" 通常包括以下几个部分: 1. `bin...

Global site tag (gtag.js) - Google Analytics