Tom cat 7的七大特性:新特性与增强功能
作者:Avneet Mangat
1. 使用随机数令牌(nonce)来阻止跨站请求伪造(CSRF)攻击
Webopedia(在线计算机字典)这样定义跨站请求伪造(CSRF):“一种恶意攻击基于web的应用程序。一次典型的恶意攻击将迫使用户在登录可信任站点的时候执行一些不必要的操作。”对CSRF更形象的定义是session riding(子乌注:好吧,这个“更形象”的定义我实在看不懂……可参看session riding)。
阻止CSRF的典型做法就是使用随机数令牌,在wikipedia中对它的定义是“一个用于认证协议的随机或伪随机数,以确保老的通信不会在重播攻击中被复用。”
Tom cat 7 有一个servlet过滤器,用于在每次提交请求之后在用户的会话中保存一个随机数令牌。这个随机数令牌必须添加到后续的每一个请求中做为一个请求参数。这个servlet过滤器会检测这个请求参数是否与存储于用户会话中的随机数令牌一致。如果一致,请求就只能是来自指定站点。如果不同,这个请求会被认为是来自不同的站点并被拒绝。
servlet过滤器非常简单。这里有一个相关源码(来自Apache Software Foundation CsrfPreventionFilter 文档)的片断:
Language: Java
public class CsrfPreventionFilter extends FilterBase {
...
...
...
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
...
...
...
String previousNonce = Param eter(Constants.CSRF_NONCE_REQUEST_PARAM);
String expectedNonce =(String) Session(true).getAttribute(Constants.CSRF_NONCE_SESSION_ATTR_NAME );
if (expectedNonce != null && !expec tedNonce.equals(previousNonce)) {
res.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
String newNonce = generateNonce();
...
...
...
所以每个URL都必须包含一个从用户会话中获取的随机数令牌。这是一个使用JSP-EL的示例:: Before:
Language: XML
1
2
3
4
<c:url var="url" value="/show" >
<c:param nam e="id" value="0" />
servlet和tomcat的关系</c:url>
<a href="${show}" >Show</a>
After:
Language: XML
<c:url var="url" value="/show">
<c:param nam e="id" value="0" />
<c:param name="org.apache.catalina.filters.CSRF_NONCE" value="${apache.catalina.filters.CSRF_NONCE}" />
</c:url>
<a href="${show}">Show</a>拿附件Tom cat 7 示例的样本工程作为示例。l 文件中配置了过滤器,随着这个过滤器的到位,所有访问localhost:8080/tom cat7dem o/csrf/ URL的请求如果没有将随机数令牌作为请求参数都会返回403错误(“访问被拒绝”)。
一个非法请求(如在垃圾邮件中)不可能拥有随机数令牌。因此,一个session riding攻击无法奏效。即使如果用户点击了一个恶意链接或提交了一个恶意表单,请求也会被拒绝,因为没有随机数令牌。随机数令牌目前只会存在于web应用返回的web页面中。
这种方法的缺陷是所有的URL链接都必须带着这个随机数令牌做请求参数。
2. 验证时改变jsessionid 以防止固定会话攻击
一个固定会话攻击发生时可能像这样:
一个恶意用户访问一个站点后,浏览器会有一个cookie存放jsessionid————即使用户没有登录。然后他伪造一个带有jsessionid的URL并将它发送给受害者(如example/login?JESSIONID=qwerty).
受害者点击带有该jsessionid的URL并被提示输入验证信息。受害者登录。
恶意用户现在可以使用带着该jsessionid的URL来以受害者的身份登录网站。
攻击者将一个jsessionid加入URL中或通过一个恶意表单将其提交到http头中是很常见的。(如果需要一个固定会话攻击的完整描述,参看来自Acros Security的白皮书“Session Fixation Vulnerability in Web-based Applications“)。
Tom cat团队实现的解决方案是打个补丁:认证后改变jsessionid。这个补丁已经在Tom cat 7中起效并且向后兼容至Tom cat 5和6,只是有一些区别。
Mark Thom as关于Tom cat 7下这个补丁的效果的描述:
默认情况下由于会话ID在验证结束后会发生改变,Tom cat并不容易受到攻击。
如果默认配置被用户修改(如,因为程序不能处理不断变化的会话ID),那可以通过禁用URL 会话跟踪(Servlet 3的新特性)来降低风险。
在Tom cat 5和6中,这个补丁的效果:
通过启用Tom cat在验证时改变会话ID可以避免固定会话攻击(如果足够的支持,这是默认启
用的)。
如果应用程序无法处理一个不断变化的会话ID,那可以通过写一个自定义过滤器检测request.isRequestedSessionIdFromURL()并做出相应回应(例如拒绝请求)来降低风险。上述变动会在幕后悄悄地进行,开发者无须做任何事情。用户会话(jsessionid)在登录后发生改变。这将会彻底杜绝固定会话攻击。
3. 内存泄露检测与预防
程序员在他们的开发环境中部署更新版本的web应用程序时经常会遇到错误Permgen space: OutOfMemoryError。这是由内存泄露导致的。上一次部署的类并没有被完全地垃圾收集。开发人员一般通过增加内存PermGen的大小和重启Tom cat来解决这个问题。
Tom cat 7推出了一个新特性来解决由于PermGen空间中移除引用的对象没有被垃圾收集导致的内存泄露。该功能是用于程序员部署应用到开发环境的。在开发环境中,为了节约时间程序员会试着在不重启Tom cat的情况下重新部署新war文件。在产品部署时,比较好的方式是停止Tom cat,清空work目录,部署新应用。
但这个内存泄露检测与预防功能并不完美。依然存在Tom cat无法处理内存泄露并且也无法检测的情况。所以对于产品系统来说,最好还是停止Tom cat,清空work目录以及旧的web应用,然后部署新web应用再重启Tom cat。
Mark Thom as解释了哪些应用或者库代码可能触发这个情势:
JDBC驱动器注册
一些日志框架
保存对象到ThreadLocals并且不移除他们
启动线程而不停止他们
还有很多地方存在使用标准Java Api可能导致类似的问题。他们包括:
使用javax.imageio API (Google Web Toolkit会触发它)
使用java.beans.Introspector.flushCaches() (Tom cat使用这个来防止由于缓存导致的内存泄露。)
使用XML解析(根本原因未知,和JRE中的bug有关)
使用RMI (有点讽刺的是导致泄露的原因和垃圾收集器有关)
在JAR文件中读取资源
4. 使用别名在War文件外存储静态内容
一个web应用可能需要静态资源,如CSS,JavaScript,以及视频和图像文件。这些通常是包含在包含在绑定的war文件中。这会增加war文件的大小并会导致静态资源的冗余。对这个的替代方案是使用Apache HTTP服务器来存放静态内容。这是从f中显示别名的相关片断:
Language: Apache configuration
<Directory "/home/avneet/temp/static">
Order allow,deny
Allow from all
</Directory>
Alias /static "/hom e/avneet/tem p/static"上述的Apache指令将让目录/home/avneet/temp/static下的内容在URLlocalhost/stati c/下可见。
Tom cat 7 现在提供了一个替换方法。Tom cat 7允许context元素上有一个新的属性aliases。这个新属性可以指向一个静态的资源。你现在可以通过ResourceAsStream('/static/...')来访问它或者在给它设一个link值,让Tom cat解析其绝对路径。下面是一个l的示例:
Language: XML
<?xml version="1.0" encoding="UTF-8"?>
<context path="/tom cat7dem o" aliases="/static=/home/avneet/temp/static"> ...
...
...
</Context>假设目录/home/avneet/tem p/static 包含图片bg.png 而且l 文件已经编辑为如上内容。
如果war 文件部署为tom cat7dem o, 你现在可以通过下面的三种方式访问这个映射的图片资源:
直接访问: localhost:8080/tom cat7dem o/static/bg.png
在HTML页面中内嵌一个链接:< img src="/tom cat7dem o/static/bg.png" / >
在Java代码中访问:ByteArrayInputStream bais = (ByteArrayInputStream)getServletContext().getResourceAsStream("/static/bg.pn g");(子乌注:我不太喜欢这种方式,这意味着将你的应用程序与Tom cat绑定,如果需要更换web容器的话,会是一个有些麻烦的事情。)
使用这个别名而非f中Apache别名的优势在于该映射资源可以从一个servlet中访问,而且这个别名能够被用于不是以Apache做前端服务器的应用程序。
Tom cat 7 加强:进化性改变
这个部分将讨论前面定义的三个增强功能。
5. Servlet 3.0, JSP 2.2 和JSP-EL 2.2 支持
Servlet 3.0增强的部分:
能将添加注释的POJO作为servlet和(或)过滤器使用(不再需要l)(子乌注:啊,我爱死这点了~~)
可以在Web fragments中解析部署————Web fragments是只包含部分部署信息的XML 文件。Servlet引擎根据这些Web fragments构造最终的l。这个可以用来降低l文件的复杂度。
举例,struts.jar和spring-m vc.jar可以有一个l。这个保存于JAR中的l会被自动检测到而struts/spring-m vc servlet和过滤器会被自动配置。异步处理Web请求(这个功能在Tom cat 6中已经生效不过现在在Servlet 3/Tom cat 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. 更容易将Tom cat内嵌入你的应用程序
Tom cat现在可以内嵌进一个应用程序,而且它可以通过编程进行配置及启动。CATALINA_HOME/l中的大部分配置可以通过编程完成。在TOm cat 7之前,Tom cat 6提供了一个Embedd类,提供了便利的方法来配置Tom cat。这个类现在已经不推荐使用。新的类Tom cat使用了一些配置单元的默认值并提供了更简单易用的方法来内嵌Tom cat。
这里是一些来自CATALINA_HOME/l的Tom cat配置单元的常用结构和一些相关属性:
Language: XML
<Server>
<Service>
<Connector port="8080">
<Engine>
<Host appBase="/home/avneet/work/tom cat7dem o/dist" />
</Engine>
</Connector>
</Service>
</Server>为了程序化的配置这些,你必须建立所有上述对象并配置他们,下面是一份完成这个工作的Java代码:
Language: Java
final String CATALINA_HOME = "/home/avneet/work/temp/tom cat7dem o/";
Tom cat tom cat = new Tom cat();
tom cat.setBaseDir( CATALINA_HOME );
tom cat.setPort( 8080 );
tom cat.addWebapp("/tom cat7demo", CATALINA_HOME + "/webapps/tom cat7dem o.war");
tom cat.start();
System.out.println("Started tom cat");
Server().await(); //保持Tom cat一直运行,直到被关闭
//Webapp tom cat7dem o accessible at localhost:8080/tom cat7demo/7. 异步日志
Tom cat 7 现在包含了一个异步文件日志记录器(AsyncFileHandler). AsyncFileHandler 扩展了FileHandler 并能替换FileHandler。要使用AsyncFileHandler,只要简单地将CATALINA_HOME/conf/logging.properties文件中所有出现的FileHandler替换为AsyncFileHandler。应用程序必须使用java.util.Logging; 因为Log4j还不支持异步日志记录。
当一个条日志信息发送给AsyncFileHandler时,日志信息会添加到一个queue(urrent.LinkedBlockingDeque),然后这个调用记录信息的方法会立刻返回,无须等待I/O到磁盘。当AsyncFileHandler被class loader加载时一个独立的线程会启动。这个线程从队列中读取日志信息并将其写入到磁盘。
这个方法的优势在于当I/O输出磁盘很慢的时候(例如,日志文件存放在远程驱动器上),日志记录不会拖慢请求处理。
AsyncFileHandler与队列之间采用生产者/消费者的关系来处理日志信息储存。标准的队列大小为10000。当溢出的时候,默认的行为是丢掉最后一条信息。默认大小和溢出行为都可以通过修改启动系统属性来配置。
关于Tom cat 7 演示程序
附件Tom cat 7 Dem o web应用程序有两个servlet。一个servlet演示如何使用随机数令牌来防止CSRF,第二个演示了别名的用法。更新web/l 文件,指向images目录的绝对路径(如 ./images).
使用l来编译war文件,并将其部署到Tom cat 7上。使用下列两个URL来查看CSRF

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。