Interface存在的原因有二:
1.能夠向上轉型為多個型別
2.讓客戶端無法產生物件,確保"介面"的設計意義
如果使用的base class不帶任何函式定義式或任何成員變數
應優先選用Interface,其次才考慮abstract class
基本上在確定某些東西會成為base class,優先考量就是使他成為Interface
過度使用Interfaces會帶來額外的複雜度,必須確定有需求再使用
在類別實作多個Interface時
有不同的Interface間採用相同的method命名會導致出錯,應避免此情形
將Interfaces置於某個class中會形成巢狀的Interfaces
巢狀的Interfaces可以為private,意義是實作他的類別在外部不能向上轉型
而巢狀位於另一個Interface內時,那些Interfaces會自動成為public
2011年6月16日 星期四
2011年6月14日 星期二
Java使用多形時可能犯的錯誤
1.覆寫 private method
import static net.mindview.util.Print.*;
public class PrivateOverride{
private void f(){ print("private f()"); }
public static void main(String[] args){
privateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride{
public void f(){ print("public f()"); }
}
//output:private f()
private method會自動成為final,也會被derived class遮蔽
例子中的Derived的f()是新的method
2.fields及static methods
物件只有一般的method可以是多形
假如base class 與 derived class 有相同的data member
derived class實際上包含了兩個同名的field,其中一個是繼承而來的
只是要呼叫base class的field就必須使用 super.field 的形式來取得
不過在實務上幾乎不會發生,將fields都宣告為private而不直接存取才是避免混淆的方法
static methos是伴隨著物件,而非個別的objects
import static net.mindview.util.Print.*;
public class PrivateOverride{
private void f(){ print("private f()"); }
public static void main(String[] args){
privateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride{
public void f(){ print("public f()"); }
}
//output:private f()
private method會自動成為final,也會被derived class遮蔽
例子中的Derived的f()是新的method
2.fields及static methods
物件只有一般的method可以是多形
假如base class 與 derived class 有相同的data member
derived class實際上包含了兩個同名的field,其中一個是繼承而來的
只是要呼叫base class的field就必須使用 super.field 的形式來取得
不過在實務上幾乎不會發生,將fields都宣告為private而不直接存取才是避免混淆的方法
static methos是伴隨著物件,而非個別的objects
Java關鍵字-final
final這個關鍵字依照使用的地方不同會有不同的效果及意義
以3個可以使用final的地方來分析:data、method、classes
final data-
告訴編譯器某塊資料是固定不變
但是在用來修飾object reference時須注意
final 會讓reference固定指向一個物件,但該物件的內容卻還是可以更動,array也是相同情況
Java允許產生留白的finals(blank final)
能宣告資料成員為final但不給予初始值,以保持彈性
例如:
public class BlankFinal{
private final int i = 0; //Initialized final
private final int j; //Blank final
public BlankFianl(){
j = 1; //Initialized blank final
}
public BlankFianl(int x){
j = x; //Initialized blank final
}
}
編譯器會強迫必須對所有的finals賦值
如果不是在定義處,就得在建構式中以運算式設定其值
此外,Java也允許將引述宣告為final,意指無法在函式中另該引數改指他處
如: void doSth(final objectA a){...}
final methods-
使用final methods的原因是鎖住這個函式,使繼承者無法進行override
class中所有的private函式自然就會是final
所以將final用在private函式上沒有意義
假使嘗試要override private method,編譯器只會將其視為該class新建立的函式而不會override
final classes-
將class宣告為final表示此class不允許被繼承
以3個可以使用final的地方來分析:data、method、classes
final data-
告訴編譯器某塊資料是固定不變
但是在用來修飾object reference時須注意
final 會讓reference固定指向一個物件,但該物件的內容卻還是可以更動,array也是相同情況
Java允許產生留白的finals(blank final)
能宣告資料成員為final但不給予初始值,以保持彈性
例如:
public class BlankFinal{
private final int i = 0; //Initialized final
private final int j; //Blank final
public BlankFianl(){
j = 1; //Initialized blank final
}
public BlankFianl(int x){
j = x; //Initialized blank final
}
}
編譯器會強迫必須對所有的finals賦值
如果不是在定義處,就得在建構式中以運算式設定其值
此外,Java也允許將引述宣告為final,意指無法在函式中另該引數改指他處
如: void doSth(final objectA a){...}
final methods-
使用final methods的原因是鎖住這個函式,使繼承者無法進行override
class中所有的private函式自然就會是final
所以將final用在private函式上沒有意義
假使嘗試要override private method,編譯器只會將其視為該class新建立的函式而不會override
final classes-
將class宣告為final表示此class不允許被繼承
2011年6月10日 星期五
Eclipse上安裝Spring IDE套件
Eclipse版本:Eclipse Java EE IDE 3.6.2 Helios
在Eclipse中輸入Spring的updatesite安裝Spring IDE
updatesite:http://springide.org/updatesite
安裝選擇 Core / Spring IDE 、Extensions(Incubation) / Spring IDE、Resources / Spring IDE
以上三項應該就可以了
遇到無法安裝的情形時
可以嘗試先安裝AJDT套件,簡單查一下資料發現這似乎是AOP技術的一種
套件位置:http://www.eclipse.org/ajdt/
挑最新的版本安裝即可
在Eclipse中輸入Spring的updatesite安裝Spring IDE
updatesite:http://springide.org/updatesite
安裝選擇 Core / Spring IDE 、Extensions(Incubation) / Spring IDE、Resources / Spring IDE
以上三項應該就可以了
遇到無法安裝的情形時
可以嘗試先安裝AJDT套件,簡單查一下資料發現這似乎是AOP技術的一種
套件位置:http://www.eclipse.org/ajdt/
挑最新的版本安裝即可
Java基本型別資訊
Java在運作上還是會將基本型別轉換成物件
透過自動封箱(autoboxing)將基本型別轉換成外覆類別
Java在class的data member為基本型別時會給予預設值
但在區域變數則不成立並會引發錯誤
所以在建立基本型別的物件時最好還是給訂初始值
基本型別 大小 外覆類型 預設值
boolean - Boolean false
char 16-bit Character '\u0000'(null)
byte 8-bit Byte (byte)0
short 16-bit Short (short)0
int 32-bit Integer 0
long 64-bit Long 0L
float 32-bit Float 0.0f
double 64-bit Double 0.0d
高精度數值
BigInteger - 提供的整數支援任意精度,可以很精確的表達任意長度的整數數值
BigDecimal - 提供任意精度的定點數,在需要精確小數點後計算的場合中適用
高精度的以上兩個類別雖然可以被視為外覆類別,但沒有對應的基本型別
在int或float型別能做到的在這兩個型別也能做到
只是必須以函式叫用方式取代基本型別的運算子,且速度比較慢
屬於以速度換取精度
透過自動封箱(autoboxing)將基本型別轉換成外覆類別
Java在class的data member為基本型別時會給予預設值
但在區域變數則不成立並會引發錯誤
所以在建立基本型別的物件時最好還是給訂初始值
基本型別 大小 外覆類型 預設值
boolean - Boolean false
char 16-bit Character '\u0000'(null)
byte 8-bit Byte (byte)0
short 16-bit Short (short)0
int 32-bit Integer 0
long 64-bit Long 0L
float 32-bit Float 0.0f
double 64-bit Double 0.0d
高精度數值
BigInteger - 提供的整數支援任意精度,可以很精確的表達任意長度的整數數值
BigDecimal - 提供任意精度的定點數,在需要精確小數點後計算的場合中適用
高精度的以上兩個類別雖然可以被視為外覆類別,但沒有對應的基本型別
在int或float型別能做到的在這兩個型別也能做到
只是必須以函式叫用方式取代基本型別的運算子,且速度比較慢
屬於以速度換取精度
2011年5月4日 星期三
[轉載] FreeMarker IDE
環境說明
作業環境:Windows XP SP3軟體版本:
- Eclipse v3.4.2
說明:FreeMarker 是一套 Java 的樣板引擎,然而 Eclipse 沒有支援 FreeMarker 所以要透過外掛,安裝FreeMarker IDE 可以將 FreeMarker 的語法加上色彩標記,這樣撰寫 FreeMarker 可以比較清楚。
Update Site: http://download.jboss.org/jbosstools/updates/stable官方網站:http://freemarker.sourceforge.net/
版本更新
安裝步驟
- 請參考 Subclipse 這篇文章使用 Eclipse 內建的「Software Updates...」來安裝來安裝
- 因為 FreeMarker IDE 是由 JBoss 所維護的,所以有許多的 JBoss 的外掛,基本上只要勾選「FreeMarkerIDE Feature」並按下「Install...」即可
- 安裝完後,附檔名為「ftl」的 FreeMarker 樣板檔就會改變圖示。
- 開啟編輯就會有色彩標示了。
2011年3月18日 星期五
[轉載] 詳細解讀Tomcat 7的七大新特性
Tomcat的7引入了許多新功能,並對現有功能進行了增強。很多文章列出了Tomcat 7的新功能,但大多數並沒有詳細解釋它們,或指出它們的不足,或提供代碼示例。本文將明確描述TOMCAT 7中七個最顯著的特徵和新增的功能,並對其作出評論,而不是僅僅列出新的功能。本文還提供了代碼例子以方便你可以對其有更好的理解。
本文分為兩個部分,分別是「TOMCAT 7的新特性」和「TOMCAT 7」增強的功能。
TOMCAT 7新特性
1 使用隨機數去防止跨站腳本攻擊。
2 改變了安全認證中的jessionid的機制,防止session攻擊。
3 內存洩露的偵測和防止
4 在war文件外使用別名去存儲靜態內容。
TOMCAT 7的增強功能
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文檔中摘錄的片段:
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中構造鏈接可以這樣:
而現在可以這樣:
具體的例子可以參考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文件的配置摘錄:
以上的設置,使得訪問http://localhost/static時,能訪問到放在/home/avneet/temp/static下的資源。
允許使用新的aliases屬性,指出靜態文件資源的位置,可以通過使用 Classloader.getResourceAsStream('/static/...')或者在鏈接中嵌入的方法讓TOMCAT去解析絕對路徑, 下面是一個在context.xml中配置的例子:
假設/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中的一些相關屬性和配置:
我們可以通過程序去進行動態設置了:
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/
本文分為兩個部分,分別是「TOMCAT 7的新特性」和「TOMCAT 7」增強的功能。
TOMCAT 7新特性
1 使用隨機數去防止跨站腳本攻擊。
2 改變了安全認證中的jessionid的機制,防止session攻擊。
3 內存洩露的偵測和防止
4 在war文件外使用別名去存儲靜態內容。
TOMCAT 7的增強功能
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 {
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: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 >
< 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"
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 >
< 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 >
< 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/
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/
訂閱:
文章 (Atom)