詳解Tomcat 7的七大新特性和新增功能

Apache發佈首個Tomcat 7版本已經發布了有一段時間了,Tomcat 7引入了許多新功能,並對現有功能進行了加強。不少文章列出了Tomcat 7的新功能,但大多數並無詳細解釋它們,或指出它們的不足,或提供代碼示例。本文將明確描述Tomcat 7中七個最顯著的特徵和新增的功能,並對其做出評論,而不是僅僅列出新的功能。本文還提供了代碼例子以方便你能夠對其有更好的理解。java

本文分爲兩個部分,分別是」Tomcat 7的新特性」和「Tomcat 7加強的功能」。程序員

Tomcat 7新特性web

1 使用隨機數去防止跨站腳本攻擊。spring

2 改變了安全認證中的jessionid的機制,防止session攻擊。apache

3 內存泄露的偵測和防止瀏覽器

4 在war文件外使用別名去存儲靜態內容。spring-mvc

Tomcat 7的加強功能tomcat

5 對Servlet 3.0,JSP 2.2和JSP-EL 2。2的支持安全

6 更容易將Tomcat內嵌到應用去中去,好比JBoss服務器

7 異步日誌記錄

根據Mark Thomas,Tomcat 7委員會的經理的說法,Tomcat 7最顯著的三個特徵是Servlet 3.0,內存檢測泄露和加強的安全特性。

Tomcat 7的例子程序中,包含了Eclipse的工程文件和Ant的構建文件,以方便去構建war文件。其中Eclipse工程文件有例子代碼描述了Tomcat 7的一些新特性。

下面逐一開始介紹。

Tomcat 7新特性

1、使用隨機數去防止跨站請求僞造攻擊

Wikipedia將跨站請求僞造攻擊(Cross Site Request forgery,CSRF)定義爲:「一種影響Web應用的惡意攻擊。CSRF讓用戶當進入一個可信任的網頁時,被強行執行惡意代碼。

經典的防止CSRF攻擊的方法是使用隨機數的方式,Wikipedia中定義爲「利用隨機或僞隨機數嵌入到認證協議中,以確保舊的不能在之後的重放攻擊中被利用。」

Tomcat 7中有一個servlet過濾器,用於將隨機數存儲在用戶每次請求處理後的seesion會話中。這個隨機數,必須做爲每次請求中的一個參數。 Servlet過濾器而後檢查在請求中的這個隨機數是否與存儲在用戶session中的隨機數是同樣的。若是它們是相同的,該請求是判斷來自指定的網站。若是它們是不一樣的,該請求被認爲是從其餘網站發出而且會被拒絕。

這個servlet過濾器是十分簡單的,下面是從TOMCAT 源代碼CsrfPreventionFilter文檔中摘錄的片斷:

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地址中都有一個從用戶session中提取的隨機數,下面是使用的JSTL例子:

在之前,JSTL中構造連接能夠這樣:

< c:url var="url" value="/show" > < c:param name="id" value="0" / > < /c:url > < a href="${show}" >Show< /a >

而如今能夠這樣:

< 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 >

具體的例子能夠參考Tomcat 7自帶例子中的演示,這個過濾器能夠在web.xml中進行配置,配置後,全部訪問如:http://localhost:8080/tomcat7demo/csrf/的都必須帶上參數,不帶上參數的話會出現403禁止訪問錯誤。

固然這種方法的缺點就是全部的連接都必須帶上這個隨機數。

2、改變了安全認證中的jessionid的機制,防止session攻擊

Session劫持攻擊一般是如下的狀況:

1 惡意攻擊者先訪問一個網頁,因爲cookie是以jsession id的方式存儲在瀏覽器中的,即便攻擊者不登錄,他能夠僞造一個帶有jsession id的地址,把它發給受害者,好比:http://example.com/login?JESSIONID=qwerty

2 受害者點這個帶有jsessionid的連接,提示輸入驗證信息以後就登錄系統。

3 攻擊者如今使用這個帶jsessionid的連接,以受害者的身份登錄進系統了。

對於攻擊者來講,將jsessionid加在url中以及經過一個惡意表單發送出去是很容易的事,對於session劫持攻擊的更詳細描述,請參考Acros Security組織的白皮書「Session Fixation Vulnerability in Web-based Applications」。

Tomcat 7對此的解決方案是一個補丁,它在驗證後改變了jsessionid。這個補丁主要是應用在Tomcat 7中,固然在TOMCAT 5和6中也可使用但只是有些不一樣。

根據Mark Thomas說的,應用了Tomcat 7的這個補丁後:

◆ TOMCAT默認狀況下安全性再也不變得脆弱,由於驗證後會話發生了變化

◆ 若是用戶改變了默認設置(好比應用程序不能處理變化了的session id),風險也會降到最小,由於在Servlet 3中,能夠禁止在url中進行會話跟蹤。

而在TOMCAT 5和TOMCAT 6中,應用了補丁後:

◆ 能阻止session劫持攻擊,由於能讓TOMCAT在驗證後改變session id。

◆ 若是應用程序不能處理變化了的session id,能夠經過寫自定義的過濾器去檢查request.isRequestedSessionIdFromURL()和其返回的結果,以下降風險。

以上這些改變都是TOMCAT在幕後所作的,開發者根本不用去理會。

3、內存泄露的偵測和防止

開發者在部署他們寫的程序到生產環境上時,常常會遇到Pemgen錯誤:OutOfMemoryError。這是因爲內存泄露而引發的。一般開發者是經過增大permgen內存的大小去解決或者就是從新啓動tomcat。

Tomcat 7包含了一個新的特性,它經過把不能垃圾回收的引用對象移走的方法,能解決一些Permgen內存泄露的問題。這個特性對程序員部署應用程序在他們的開發環境中是十分方便的,由於程序員在開發環境中爲了節省時間通常不從新啓動Tomcat就能部署新的war文件。在生產環境中,最好的建議仍是停掉TOMCAT,而後清除work下面的目錄文件而且從新部署應用。

固然,內存泄露檢測和防止這個特性如今還不是很完善,仍是有的狀況TOMCAT不能檢測內存泄露和修復之的,因此對於生產環境,最好的的辦法仍是停掉TOMCAT,而後清除work下面的目錄文件而且從新部署應用。

Mark Thomas解析應用程序或者庫程序在以下狀況下會觸發內存泄露:

◆ JDBC驅動的註冊

◆ 一些日誌框架

◆ 在ThreadLocals中保存了對象但沒有刪除它們

◆ 啓動了線程但沒中止

而 Java API 存在內存泄漏的地方包括:

1.使用 javax.imageio API ( Google Web Toolkit會用到)

2.使用 java.beans.Introspector.flushCaches()

3.使用 XML 解析器

4.使用 RMI 遠程方法調用

5.從 Jar 文件中讀取資源

4、在war文件外使用別名去存儲靜態內容

Web應用程序須要靜態資源文件,好比象CSS,Javascript和視頻文件、圖片文件等。一般都把它們打包放在war文件中,這將增長了WAR文件的大小而且致使不少重複的加載靜態資源。一個比較好的解決方法是使用Apache HTTP服務器去管理這些靜態文件資源,下面是一個apache httpd.conf文件的配置摘錄:

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

以上的設置,使得訪問http://localhost/static時,能訪問到放在/home/avneet/temp/static下的資源。

容許使用新的aliases屬性,指出靜態文件資源的位置,能夠經過使用Classloader.getResourceAsStream('/static/...')或者在連接中嵌入的方法讓TOMCAT去解析絕對路徑,下面是一個在context.xml中配置的例子:

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

假設/home/avneet/temp/static這個文件夾存放有一張圖片bg.png,若是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");

使用aliases的好處是能夠代替Apache的httpd.conf的設置,而且能夠在servlet容器範圍內訪問,而且不須要Apache。

Tomcat 7的加強特性

5、對Servlet 3.0,JSP 2.2和JSP-EL 2.2的支持

Servlet 3的加強特性有:

◆ 能夠在POJO或者過濾器filters中使用annotations註釋(在web.xml中再也不須要再進行設置了)

◆ 能夠將web.xml分塊進行管理了。也就是說,用戶能夠編寫多個xml文件,而最終在web.xml中組裝它們,這將大大下降web.xml的複雜性加強可讀性。好比, struts.jar和spring-mvc.jar每個均可以有一個web-fragment.xml。開發者再也不須要在web.xml中去配置它們了,在web-fragment.xml中的jar文件會自動加載,而且struts/spring-mvc servlets和filters也會自動裝配設置。

◆ 異步處理web的請求----這個特性在tomcat 6 中已經有了,如今在Tomcat 7中以Servlet 3標準規範化了,能讓使用異步I/O的web應用程序能夠移植到不一樣的web容器中。異步處理使用非阻塞I/O,每次的HTTP鏈接都不須要對應一個線程。更少的線程能夠爲更多的鏈接提供服務。這對於須要長時間計算處理才能返回結果的情景來講是頗有用的,好比產生報表,Web Servce調用等。

◆ 安全的加強---Servlet 3.0如今使用SSL 去增強了會話session的跟蹤,代替了原來的cookie和URL重寫。

6、更容易將Tomcat內嵌到應用去中去

Tomcat 7如今能夠嵌入到應用程序中去,並能夠經過程序去動態設置和啓動。象在CATALINA_HOME/conf/server.xml中的不少配置,如今均可以用程序動態去設置了。在Tomcat 7前,Tomcat 6提供了一個嵌入類,它能方便地去配置Tomcat。但在Tomcat 7中,這個類已被廢棄了。這個新的Tomcat 7的類,使用了幾個默認的配置元素,並提供了一個更容易和簡單的方法去嵌入Tomcat。

下面是CATALINA_HOME/conf/server.xml中的一些相關屬性和配置:

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

咱們能夠經過程序去進行動態設置了:

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(); //Keeps Tomcat running until it is shut down  //Webapp tomcat7demo accessible at http://localhost:8080/tomcat7demo/

7、異步日誌記錄

Tomcat 7如今包括了一個異步日誌記錄器(AsyncFileHandler)。AsyncFileHandler繼承了FileHandler類並能代替FileHandler。使用AsyncFileHandler,時,只須要在CATALINA_HOME/conf/logging.properties中把FileHandler所有替換爲AsyncFileHandler就能夠了。要注意的是異步日誌不能跟log4一塊兒工做。

當有日誌發向AsyncFileHandler時,日誌被加入到隊列中(java.util.concurrent.LinkedBlockingDeque)而且方法調用的信息會立刻返回不須要等待I/O寫到磁盤中。當類加載器加載AsyncFileHandler時,會有一個單獨的線程啓動,這個線程會從隊列中讀取日誌信息而且寫到磁盤中去

這種方法的好處是若是I/O速度很慢(好比日誌要保存在遠端的設備上)時,記錄日誌的請求和處理過程不會顯得很慢。

AsyncFileHandler使用生產者和消費者的關係原理,在隊列中存儲日誌信息。隊列默認大小爲10000。爲了預防隊列溢出,默認是丟棄最後的信息。默認的隊列大小和溢出的設置均可以經過啓動參數進行設置。

關於Tomcat 7的示例程序

Tomcat 7的自帶程序例子有兩個servlets,一個是演示瞭如何採用隨機數的辦法防止CSRF攻擊,另一個是描述了使用aliases。更新一下web/META-INF/context.xml,指出圖片的絕對路徑便可順利運行。

經過ant運行build.xml去將它們部署到Tomcat 7中,使用以下兩個地址訪問:

◆ http://localhost:8080/tomcat7demo/csrf/

◆ http://localhost:8080/tomcat7demo/alias/

相關文章
相關標籤/搜索