[書籍導讀]
Tomcat 技術手冊
Tomcat 設定技巧 - Top 10
作者:Jason Brittain & Ian F. Darwin
出處:http://www.onjava.com/lpt/a/3909
按:現在開發 Java Web 應用,已是建立和部署 Web 內容常用的方式。全球的使用者漸漸發現到以
Jakarta Tomcat 作為 Servlet 和 JSP container 的好處。Tomcat 是自由軟體、跨平臺、有許多功能特色,並且發展迅速,現在已十分地流行。
唯一的環節就是:如何按照你的需求去設定 Tomcat 呢?只要你能設定到符合要求,Tomcat
必能如你所願。下面是十項關於 Tomcat 的組態設定技巧,這些技巧源自於筆者拙著《Tomcat: The Definitive
Guide》(中文版《Tomcat 技術手冊》),希望對你有所幫助。
- Jason Brittain
1. 設定 Admin Web Application
大多數商用的 J2EE 伺服器都會提供全功能的管理界面,而且許多界面還可以經由 web 應用程式來存取。Tomcat
Admin 應用程式也快要成為全功能的 Tomcat 管理工具,以與這些商用產品相庭抗禮。此程式首先出現在 Tomcat 4.1 中,並且已能提供範圍、資料來源、以及使用者與群組的控制。你也可以控制像初始化參數,以及在各種不同的使用者資料庫中的使用者、群組、與角色。在未來的發行版中,其功能還會再加強,不過,目前的實作已經證實是相當有用的。
Admin web 應用程式是定義在 CATALINA_BASE/webapps/admin.xml
中。
你必須編輯此檔,以確保在 Context
元素的 docBase
標記屬性中所設定的路徑是絕對的,亦即,CATALINA_HOME/server/webapps/manager 的絕對路徑(譯註:CATALINA_HOME
即 tomcat 安裝目錄)。另一種方式是,你可以移除自動部署的檔案,並在 server.xml 檔中手動地設定 Admin
範圍。在不會被此應用程式管理的機器上,應該可以刪除 CATALINA_BASE/webapps/admin.xml 來停用它。
如果使用 UserDatabaseRealm(預設),就需要新增一個使用者以及一個角色到
CATALINA_BASE/conf/tomcat-users.xml 檔中。現在,請編輯這個檔,加入「admin」角色到使用者資料庫中,如下:
<role
name="admin"/>
另外還要一個設定為「admin」角色的使用者。請於現有的使用者資料之後,加入以下這一行(請改變密碼使其更加安全):
<user name="admin" password="deep_dark_secret" roles="admin"/>
完成這些步驟後,請重新啟動 Tomcat,並連到 http://localhost:8080/admin,你將看到一個登入畫面。Admin
應用程式係使用容器管理的安全機制,並以 Jakarta Struts 的架構編寫。一旦以設定為「admin」角色的使用者登入,即能夠使用
Admin 管理界面設定 Tomcat 的組態。
2. 設定 Manager 應用程式
Manager 應用程式讓你能透過比 Admin 應用程式更簡化的使用者界面,來執行簡單的管理作業。
Manager 應用程式係定義於自動部署檔 CATALINA_BASE/webapps/manager.xml
之內。
你必須編輯此檔案,確保 Context
元素的 docBase
標記屬性是絕對路徑,亦即,CATALINA_HOME/server/webapps/manager 的絕對路徑。
如果是使用預設的 UserDatabaseRealm,則需要新增使用者和角色到
CATALINA_BASE/conf/tomcat-users.xml 檔中。請編輯此檔案,新增「manager」角色到使用者資料庫中:
<role name="manager">
再來也要有一個設定為「manager」角色的使用者。在現成的使用者區塊之後加入如下的內容(記得將密碼改成比較安全的):
<user name="manager" password="deep_dark_secret" roles="manager"/>
然後重新啟動 Tomcat,連上 http://localhost/manager/list,將看到樸素的文字式管理界面,或連上
http://localhost/manager/html/list,可看到簡單的 HMTL 管理界面。不管是哪種方式都說明你的
Manager 現在已經啟動了。
Manager 應用程式讓你以非持續性的方式安裝新的 web 應用程式,亦即,作為測試用。如果在 /home/user/hello
中有一 web 應用程式,並想藉著安裝在 URI /hello 下來測試,我們在第一個文字輸入欄位(Path)中輸入「/hello」,而在第二個文字輸入欄位(Config
URL)中輸入「file:/home/ian/webs/hello」。
Manager 也能讓你停止、重新載入、刪除、或解除 web 應用程式的部署。停止應用程式會讓它無法使用,直到收到進一步的通知,不過,它當然也可以再啟動。使用者企圖存取已經停止的應用程式,將會收到錯誤訊息,如「503
- This application is not currently available」。
刪除 web 應用程式只會從 Tomcat 的現行分身中刪除 — 如果此應用程式是從組態檔啟動的,則下次再啟動
Tomcat 時,它還會再出現(亦即,刪除動作並不會自硬碟中刪除 web 應用程式的內容)。
3. 部署 web 應用程式
有兩種自動部署 web 應用程式於檔案系統上的方式:
1. 將 WAR 檔或 web 應用程式的目錄(包括所有的內容)複製到 $CATALINA_BASE/webapps
目錄中。
2. 建立只包含 web 應用程式之 Context
元素的 XML 程式片段,並將其放入 $CATALINA_BASE/webapps 中。web 應用程式本身可以存放於檔案系統中的任何位置。
如果有 WAR 檔,只需將其複製到 CATALINA_BASE/webapps 目錄中,就可部署它。檔案名稱必須以
.war 作為副檔名。當 Tomcat 發現此檔時,它(預設)會將其解開至以 WAR 檔之主檔名為名稱的子目錄中。接著,則會在記憶體中建立範圍,正如藉著編輯
Tomcat 的 server.xml 檔而產生的一樣。不過,任何必要的預設值則會來自 Tomcat 的 server.xml
檔中的 DefaultContext
元素。
部署 web 應用程式的另一種方式是撰寫 Context
的 XML 程式片段檔,然後將該檔複製到 CATALINA_BASE/webapps 目錄下。範圍的片段並不是完整的 XML
文件,而只是適合於 web 應用程式之 Context
元素及任何子元素。這些檔案就像從 server.xml 檔中切出的 Context
元素一樣,因此稱為範圍的片段。
例如,如果想要部署 MyWebApp.war 的 WAR 檔,和可存取部分該 web 應用程式的領域,則可以使用這樣的程式片段:
<!--
部署 MyWebApp.war 的範圍片段
-->
<Context path="/demo" docBase="webapps/MyWebApp.war"
debug="0" privileged="true">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Context>
請將此片段程式檔命名為 MyWebApp.xml,然後複製到 CATALINA_BASE/webapps
目錄下。
這些範圍片段提供了一種部署 web 應用程式的方便方法;不需要編輯 server.xml
檔,而且除非關閉預設的 liveDeploy
功能,否則不需再啟動 Tomcat 以安裝新的 web 應用程式。
4. 設定虛擬主機
只有在架設虛擬主機時,才需要修改 Host
元素。虛擬主機是一種機制,可以讓一個 web 伺服器行程服務多個網域名稱,而讓各個網域看來有其自己的伺服器。事實上,由於將電腦直接連上網際網路,並以足夠的頻寬提供合理的回應時間,以及使用固定的
IP 位址提供穩定度,所需花費的成本太高,因此大多數的小型商業網站都實作成虛擬主機。
在任何 web 伺服器上,藉著在「網域名稱服務」(Domain Name Service;DNS)資料中設定另一個
IP 位址,並告訴 web 伺服器將所有此位址的請求對應至特定的網頁目錄,就可以產生「以名稱為基準」的虛擬主機。因為這本書是談論 Tomcat,所以我們不會敘述在不同作業系統上設定
DNS 資料的全部方法。如果需要這方面的協助,請參閱由 Paul Albitz 與 Cricket Liu 合著的《DNS
and Bind》(O'Reilly 出版)。我們會使用靜態的 hosts 檔作為示範,因為這是設定主機別名來測試的最簡單辦法。
如欲在 Tomcat 中使用虛擬主機,你只需設定主機的 DNS 或 hosts 資料。設定 localhost
的 IP 別名,以足夠來測試了。然後,你需要在 server.xml 的組態檔中加入幾行資料:
<Server port="8005" shutdown="SHUTDOWN" debug="0">
<Service name="Tomcat-Standalone">
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"/>
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8443" minProcessors="5" maxProcessors="75"
acceptCount="10" debug="0" scheme="https" secure="true"/>
<Factory className="org.apache.coyote.tomcat4.CoyoteServerSocketFactory"
clientAuth="false" protocol="TLS" />
</Connector>
<Engine name="Standalone" defaultHost="localhost" debug="0">
<!--此為預設主機-->
<Host name="localhost" debug="0" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT" debug="0"/>
<Context path="/orders" docBase="/home/ian/orders" debug="0" reloadable="true" crossContext="true">
</Context>
</Host>
<!--此為第一個「虛擬主機」www.example.com -->
<Host name="www.example.com" appBase="/home/example/webapp">
<Context path="" docBase="."/>
</Host>
</Engine>
</Service>
</Server>
在發行時,Tomcat 的 server.xml 檔只含有一個虛擬主機,不過要加入額外的虛擬主機是相當容易的。在前面的範例中,server.xml
檔的簡化版本以粗體字顯示新增一個虛擬主機所需的所有額外結構。每一個 Host
元素至少必須含有一個 Context
元素;其中之一必須是此主機預設的 Context,其設定方式是將相對路徑設為空字串。(例如,path="")。
5. 設定基礎驗證(Basic Authentication)
當存取受保護的資源時,容器管理的驗證方法可以控制確認使用者身分的方式。當 web 應用程式使用基本驗證(在
web.xml 檔之 auth-method
元素中的 BASIC)時,每當瀏覽器請求該受保護的
web 應用程式資源時,Tomcat 會使用 HTTP 基本驗證向瀏覽器索取使用者名稱與密碼。使用這種驗證方法,所有的密碼都會以 base64
編碼的文字在網路上傳遞。
提醒:一般認為使用基本驗證是安全防護上的瑕疵,除非在用戶端與伺服端之間,網站也同時使用 HTTPS 或其它的加密方式(如虛擬私有網路;VPN)。如果沒有這種額外的加密機制,網路上的駭客可以攔截(甚至濫用)使用者密碼。但是,如果你剛開始使用
Tomcat,或者想要以 web 應用測試容器管理的安全防護,基礎驗證非常容易設定和使用。只需要加入 <security-constraint>
和 <login-config>
元素到 web 應用的 web.xml 檔中,並於 CATALINA_BASE/conf/tomcat-users.xml
中加入適當的 <role>
和 <user>
元素即可,然後重新啟動 Tomcat,剩下的 Tomcat 會幫你解決。
範例 2-6 係節錄自擁有會員獨享的子目錄(使用基本驗證)之俱樂部會員網站的 web.xml。請注意實質上這會取代
Apache web 伺服器的 .htaccess 檔。
<!--
定義會員獨享區 — 定義此應用程式的「Security Constraint」
並將其對應至想要限制的子目錄(URL)
-->
<security-constraint>
<web-resource-collection>
<web-resource-name>
Entire Application
</web-resource-name>
<url-pattern>/members/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>member</role-name>
</auth-constraint>
</security-constraint>
<!-- Define the Login Configuration for this Application -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>My Club Members-only Area</realm-name>
</login-config>
6. 單一入口(Single Sign-On)
當設定好領域及驗證方法後,你將需要處理實際的登入過程。通常對使用者來說,登入應用程式是很令人討厭的,因此你需要盡量減少必須驗證身分的次數。在預設狀況下,每個
web 應用程式會要求使用者在第一次請求受保護的資源時登入。如果你執行多個 web 應用程式,而每個程式都要求使用者驗明身分,這對使用者來說是很煩人的。使用者無法知道有多少個別的應用程式構成任何單一的網站,所以也不會知道正在請求跨越範圍邊界的資源,而會懷疑為何要重複地登入。
Tomcat 4 的「單一入口」功能可以讓使用者只需驗明身分一次。就可存取所有載入虛擬主機的 web
應用程式。如欲使用這個功能,你只需在主機的層次加入 SingleSingOn
的 Valve
元素,如下所示:
<Valve className="org.apache.catalina.authenticator.SingleSignOn"
debug="0"/>
Tomcat 發行版的預設 server.xml 檔含有被加上註解符號的單一入口的 Valve
組態範例,你可以移除註解符號並使用之。此後,在所設定虛擬主機內,任何在某範圍中被視為合法的使用者,在同一主機之所有其它範圍內都會被視為合法。
使用單一入口的門閥(valve)有一些重要的限制:
- Valve 必須被設定,並與 web 應用程式(以 Context
元素表示)皆套疊於相同的 Host
元素內
- 包含共享的使用者資訊的 Realm
必須設定在相同的 Host
層級,或設定在外一層。
- 在 Context
層級時,Realm
不能被覆蓋。
- 使用單一入口的 web 應用程式必須使用 Tomcat 內建的驗證方式之一(在 web.xml
的 auth-method
元素中),而非自訂的驗證方式。內建的方法包括基本、摘要、表單、及 client-cert 驗證。
- 如果使用單一入口,並想要在網站中整合其它第三者的 web 應用程式,而且此新的 web 應用程式使用自己的驗證程式,但不使用容器管理的安全防護機制,基本上是作不到的。對所有使用單一入口的
web 應用程式,使用者需要登入一次,然後當他們請求新的第三者的 web 應用程式時,還要再登入一次。如果你有原始程式碼,而且又是開發者,當然可以修改它,可是這可能不太容易。
- 單一入口的門閥需要使用 HTTP 的 cookie。
7. 自訂的使用者目錄(Customized User Directores)
某些網站喜歡讓個別的使用者在伺服器上發佈網頁目錄。例如,大學的學系可能會給每個學生一個公用區域,或 ISP
會在一台伺服器上釋放一些網頁空間給沒有虛擬主機的客戶。在這種情況下,一般會使用 ~ 字元加上使用者的名稱,作為該使用者網站的虛擬路徑:
http://www.cs.myuniversity.edu/~username
http://members.mybigisp.com/~username
Tomcat 提供兩種方式,依據主機來對應,它使用幾個特殊的 Listener
元素。Listener
的 className
標記屬性應為 org.apache.catalina.startup.UserConfig,而
userClass
標記屬性則指定一種對應的類別。如果你的作業系統是 Unix、並有執行 Tomcat 的帳號可讀取的標準 /etc/passwd
檔、而且該檔案設定使用者的主目錄,則請使用 PasswdUserDatabase
對應類別:
<Listener
className="org.apache.catalina.startup.UserConfig"
directoryName="public_html"
userClass="org.apache.catalina.startup.PasswdUserDatabase"/>
Web 檔案必須放入如 /home/users/ian/public_html 及
/users/jbrittain/public_html 目錄中。當然,你可以將 public_html 改成使用者置放其個人網頁的任何子目錄。
事實上,此目錄可以完全不在使用者的主目錄內。如果你沒有密碼檔,但想要從使用者名稱對應至有共同父目錄(如
/home)的子目錄,請用 HomeUserDatabase
類別:
<Listener
className="org.apache.catalina.startup.UserConfig"
directoryName="public_html" homeBase="/home"
userClass="org.apache.catalina.startup.HomesUserDatabase"/>
在此情況下,web 檔案會放入如 /home/ian/public_html 與 /home/jbrittain/public_html
的目錄中。這種格式在 Windows 比較有用,你可以使用像 C:\home 的目錄。
如果存在時,這些 Listener
元素必須放在 Host
元素內,但不能在 Context
元素內,因為 Listener
元素是套用至 Host
本身。
8. 在 Tomcat 中使用 CGI
Tomcat 主要的目的是作為 servlet/JSP 引擎,不過它卻含有大量的功能可以與傳統的 web
伺服器相抗衡。其中之一是對共用閘道界面(CGI)的支援;CGI 提供一種方式來執行外部程式,以回應瀏覽器的請求,而多半是用來處理網頁上的表單。CGI
之所以稱為通用,是因為它可以叫用以幾乎任何程式或 script 語言編寫的程式:Perl、Python、awk、Unix
的 shell script、甚至 Java。不過,由於啟動時的系統負載,你可能不會將 Java 應用程式當成 CGI 來執行;而 servlet
規格的原始設計就是要來消除這種系統負載。Servlet 幾乎永遠比 CGI 有效率,因為每次當有人點選連結或按鈕時,你並不會啟動新的作業系統層級的行程。
Tomcat 內含非必要性的 CGI servlet,以讓你執行舊式的 CGI script;前提是假設大多數新的後端處理都是交由使用者自訂的
servlet 與 JSP 來執行。
如欲啟用 Tomcat 的 CGI servlet,你必須執行下列的動作:
- 將 servlets-cgi.renametojar(可在 CATALINA_HOME/server/lib/
中找到)更名成 servlets-cgi.jar,以便讓處理 CGI script 的 servlet 會在 Tomcat
的 CLASSPATH 中。
- 在 Tomcat 的 CATALINA_BASE/conf/web.xml 檔中,移除
cgi
servlet 的定義前的註解符號(在目前的發行版中,約於第 241 行)。
- 也是在 Tomcat 的 web.xml 檔中,移除 cgi
servlet 的 servlet-mapping
元素的註解符號(在發行版中,大約於第 299 行)。請記住,這會設定指向 CGI script 的 HTML 連結。
- 將 CGI script 放在 WEB-INF/cgi 目錄之下(記住,WEB-INF
是將不想讓使用者看到的東西藏起來的安全地方),或放在範圍中其它的目錄中,並調整 cgiPathPrefix
參數,以識別包含檔案的目錄。這會設定 CGI script 的實際位置,而一般會與上一步驟的 URL 不同。
- 重新啟動 Tomcat,你的 CGI 處理作業就應該能運作了。
讓 servlet 尋找實際的 script 的預設目錄是 WEB-INF/cgi。如前所述,WEB-INF
目錄已受到保護,可防範瀏覽器的偷窺,因此這是置放 CGI script 的好地方,而這些 script 可能會包含密碼或其它機密的資訊。但是,為了維持與其它伺服器的相容性,你可能會偏好將
script 放在傳統的目錄 — /cgi-bin — 中,不過請注意,在此目錄中的檔案可能會被好奇的網際漫遊者看到。另外,在
Unix 上,請確定執行 Tomcat 的使用者有執行 CGI script 的權限。
9. 變更 Tomcat 的 JSP 編譯器
在 Tomcat 4.1(或更高版本),則是直接從 Tomcat 內使用 Ant 的程式控制器來編譯
JSP。這種作法好像有點奇怪,不過這也是 Ant 的功用之一;有一個 API 可讓開發者在不需啟動新的 JVM 的情形下,使用 Ant。這是以
Java 編寫 Ant 的好處之一。此外,這表示你現在可以使用 Ant 中之 javac 工作項目所支援的任何編譯器,這些編譯器列於
Apache Ant 手冊的 javac
文件頁面中。在使用上,這比較容易使用,因為你只需要稱為「compiler」的 init-parm,以及一個支援的編譯器名稱:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>compiler</param-name>
<param-value>jikes</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
當然,此編譯器必須安裝在系統上,而且也可能要設定 CLASSPATH。
10. 限制特定主機存取
有時,你可能只想讓來自特定的主機名稱或 IP 位址的使用者,能存取 Tomcat 的 web 應用程式。這樣一來,就只有位於指定站點的客戶端能夠取得服務的內容了。Tomcat
內有兩個 Valve
可做此用途的設定:RemoteHostValve
和 RemoteAddrValve。
這些 Valve
可以讓你用主機名稱或 IP 位址來過濾請求,並允許或拒絕比對成功的主機。其功用類似於 Apache httpd 中,以目錄為基準的
Allow/Deny
指令。如果執行 Admin 應用程式,你可能想只允許從 localhost 來存取它,如下所示:
<Context path="/path/to/secret_files" ...>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127.0.0.1" deny=""/>
</Context>
如果未給定 allow
樣式,則會拒絕符合 deny
屬性的樣式,但允許所有其它的樣式。類似地,如果未給定 deny
樣式,則會允許符合 allow
屬性的樣式,但拒絕所有其它的樣式。 |