鍍金池/ 教程/ Linux/ 重寫機制
連接器
JSPs
重寫機制
CGI
Tomcat Manager
Windows 認(rèn)證
代理支持
虛擬主機
安全性注意事項
如何在 Maven 中使用 Tomcat 庫
安裝
MBean 描述符
JNDI 資源
類加載機制
Tomcat Web 應(yīng)用部署
基于 APR 的原生庫
負載均衡器
安全管理
附加組件
監(jiān)控與管理
Windows 服務(wù)
集群化與會話復(fù)制
高級 IO 機制
SSI(服務(wù)器端嵌入)
WebSocket 支持
JDBC 數(shù)據(jù)源
日志機制
默認(rèn) Servlet
SSL/TLS 配置
Tomcat 的 JDBC 連接池
第一個應(yīng)用
簡介
Realm 配置

重寫機制

簡介

重寫 Valve(Rewrite Valve) 實現(xiàn) URL 重寫功能的方式非常類似于 Apache HTTP Server 的 mod_rewrite 模塊。

配置

重寫 Valve 是通過使用 org.apache.catalina.valves.rewrite.RewriteValve 類名來配置成 Valve 的。

經(jīng)過配置,重寫 Valve 可以做為一個 Valve 添加到 Host 中。參考虛擬服務(wù)器文檔來了解配置詳情。該 Valve 使用包含重寫指令的 rewrite.config 文件,且必須放在 Host 配置文件夾中。

另外,重寫 valve 也可以用在 Web 應(yīng)用的 context.xml 中。該 Valve 使用包含重寫指令的 rewrite.config 文件,且必須放在 Web 應(yīng)用的 WEB-INF 文件夾中。

指令

rewrite.config 文件包含一系列指令,這些指令和 mod_rewrite 所用的指令很像,尤其是核心的 RewriteRuleRewriteCond 指令。

注意:該部分內(nèi)容修改自 mod_rewrite 文檔,后者版權(quán)歸屬于 Apache 軟件基金會(1995-2006),遵循 Apache 許可發(fā)布。

1. RewriteCond

格式:RewriteCond TestString CondPattern

RewriteCond 指令定義了一個規(guī)則條件。一個或多個 RewriteCond 指令可以優(yōu)先于 RewriteRule 指令執(zhí)行。如果 URI 當(dāng)前狀態(tài)匹配它的模式,并且滿足了這些條件,才會使用下列規(guī)則。

TestString 是一種字符串,除了簡單的文本之外,它還可以含有下列擴展結(jié)構(gòu)。

  • RewriteRule backreferences 對形式 $N(0 <= N <= 9)的反向引用。提供對模式成組部分的訪問(括號中的),從屬于 RewriteCond 條件當(dāng)前狀態(tài)的 RewriteRule
  • RewriteCond backreferences
  • RewriteMap expansions
  • Server-Variables 這些是形式 %{ NAME_OF_VARIABLE } 中的變量。%{ NAME_OF_VARIABLE } 中的 NAME_OF_VARIABLE 是一種取自下面列表的字符串:

  • HTTP 報頭
HTTP\_USER\_AGENT  
HTTP\_REFERER  
HTTP\_COOKIE  
HTTP\_FORWARDED  
HTTP\_HOST  
HTTP\_PROXY\_CONNECTION  
HTTP\_ACCEPT    
  • 連接與請求
REMOTE\_ADDR  
REMOTE\_HOST  
REMOTE\_PORT  
REMOTE\_USER  
REMOTE\_IDENT  
REQUEST\_METHOD  
SCRIPT\_FILENAME  
REQUEST\_PATH  
CONTEXT\_PATH  
SERVLET\_PATH  
PATH\_INFO  
QUERY\_STRING  
AUTH\_TYPE  
  • 服務(wù)器內(nèi)部
DOCUMENT\_ROOT    
SERVER\_NAME  
SERVER\_ADDR  
SERVER\_PORT  
SERVER\_PROTOCOL  
SERVER\_SOFTWARE  
  • 日期與時間
TIME\_YEAR  
TIME\_MON  
TIME\_DAY  
TIME\_HOUR  
TIME\_MIN  
TIME\_SEC  
TIME\_WDAY  
TIME 
  • 特殊字符串
THE\_REQUEST  
REQUEST\_URI  
REQUEST\_FILENAME  
HTTPS     

這些變量對應(yīng)著相似名稱的 HTTP MIME 報頭和 Servlet API 方法。多數(shù)都記錄在各種手冊和 CGI 規(guī)范中。下面列出了重寫 Valve 專有的那些變量:

  • REQUEST_PATH
    對應(yīng)用于映射的完整路徑。
  • CONTEXT_PATH
    對應(yīng)映射的上下文的路徑。
  • SERVLET_PATH
    對應(yīng) Servlet 路徑。
  • THE_REQUEST
    由瀏覽器發(fā)送給服務(wù)器的完整 HTTP 請求代碼行(比如,GET /index.html HTTP/1.1)。這并不包括任何由瀏覽器發(fā)送的額外報頭。
  • REQUEST_URI
    HTTP 請求代碼行中所請求的資源(在上例中,應(yīng)為為 /index.html)。
  • REQUEST_FILENAME
    與請求相匹配的文件或腳本的完整本地文件系統(tǒng)路徑。
  • HTTPS
    當(dāng)連接使用 SSL/TLS 時,含有文本 "on",否則含有 "off"。

另外還需要注意的是:

  1. SCRIPT_FILENAMEREQUEST_FILENAME 含有同樣的值:Apache 服務(wù)器內(nèi)部結(jié)構(gòu) request_recfilename 字段值。第一個名稱常被稱為 CGI 變量值,第二個名稱相當(dāng)于 REQUEST_URI(包含 request_recuri 字段值)。
  2. %{ENV:variable}。其中的 variable 可以是任何 Java 系統(tǒng)屬性。目前可以使用。
  3. %{SSL:variable}。其中的 variable 是 SSL 環(huán)境變量名。目前還未實現(xiàn)。范例: %{SSL:SSL_CIPHER_USEKEYSIZE} 可能擴展到 128。
  4. %{HTTP:header}。其中的 header 可以是任意的 HTTP MIME 報頭名稱。該變量常用來獲取發(fā)送到 HTTP 請求的報頭值。范例: %{HTTP:Proxy-Connection} 是 HTTP 報頭 Proxy-Connection: 的值。

CondPattern 即條件模式,是一種應(yīng)用于 TestString 當(dāng)前實例的正則表達式。TestString 在匹配 CondPattern 之前,會首先求值。

謹(jǐn)記CondPattern 是一種兼容 perl 并帶有一些擴展的正則表達式。

  1. 可以在模式字符串前加上 ! 字符作為前綴,來指定匹配模式。
  2. CondPattern 有一些特殊變體。除了真正的正則表達式字符串外,還可以使用下列組合形式之一:
    • <CondPattern (字母順序高于)
      CondPattern 當(dāng)成一種純粹字符串,按照字母順序?qū)⑵渑c TestString 進行對比。如果在字母順序上,TestString 高于 CondPattern ,則為 true。
    • >CondPattern(字母順序低于) 將 CondPattern 當(dāng)成一種純粹字符串,按照字母順序?qū)⑵渑c TestString 進行對比。如果在字母順序上,TestString 低于 CondPattern ,則為 true。
    • =CondPattern' (字母順序等于)
      CondPattern 當(dāng)成一種純粹字符串,按照字母順序?qū)⑵渑c TestString 進行對比。如果在字母順序上,TestString 等于 CondPattern ,則為 true。
    • -d(目錄)
      TestString 當(dāng)成一種路徑名,測試它是否存在并且是一個目錄。
    • -f(常規(guī)文件) 將 TestString 當(dāng)成一種路徑名,測試它是否存在并且是一個常規(guī)文件。
    • -s(常規(guī)文件,帶有文件尺寸)
      TestString 當(dāng)成一種路徑名,測試它是否存在并且是一個文件大小大于 0 的普通文件。

注意:所有這些測試都可以加上前綴 ! 來使它們的含義反向。

  1. 可以將 [flag] 做為 RewriteCond 指令的第三個參數(shù),為 CondPattern 設(shè)定標(biāo)記。這里的 flag 是一個包含下列任一標(biāo)記,且標(biāo)記間由逗號分隔的列表:
    • nocase|NC(不區(qū)分大小寫) 無論是擴展的 TestString 還是在 CondPattern 中,都不區(qū)分大小寫(A-Z 和 a-z 是等同的)。該標(biāo)記只有在比較 TestStringCondPattern 時才是有效的。對于文件系統(tǒng)和子請求(HTTP 請求)是無效的。
    • ornext|OR(或者下一個條件) 利用本地 OR(而不是隱式的 AND)來組合規(guī)則條件。典型范例為:
RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]  
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]  
RewriteCond %{REMOTE_HOST}  ^host3.*  
RewriteRule ...some special stuff for any of these hosts...       

沒有該標(biāo)記,你必須寫三遍條件/規(guī)則對。

范例

假如想根據(jù)請求頭的 User-Agent: 對網(wǎng)站主頁進行重寫,可以使用下列代碼:

RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]

說明:如果使用的瀏覽器將它自身標(biāo)識為 'Mozilla'(包括 Netscape Navigator、Mozilla,等等),那么這就是內(nèi)容最大化主頁(max homepage。它可以包含框架或其他特性);如果使用的是 Lynx 瀏覽器(基于終端的),那么獲得的就是內(nèi)容最小化的主頁(min homepage)——專為便于瀏覽文本而設(shè)計的版本;如果這些條件都不適用(你使用的是其他瀏覽器,或者你的瀏覽器將其自身標(biāo)識為非標(biāo)準(zhǔn)內(nèi)容),那么得到的就是標(biāo)準(zhǔn)主頁(std homepage)。

2. RewriteMap

格式:RewriteMap name rewriteMapClassName optionalParameters。

通過用戶必須實現(xiàn)的一個接口來實現(xiàn)映射。類名為 org.apache.catalina.valves.rewrite.RewriteMap,代碼為:

package org.apache.catalina.valves.rewrite;

public interface RewriteMap {
public String setParameters(String params);
public String lookup(String key);
}

3. RewriteRule

格式:RewriteRule Pattern Substitution

RewriteRule 指令是重寫機制的核心。此指令可以多次使用,每個實例都定義一個單獨的重寫規(guī)則。這些規(guī)則的定義順序尤為重要,因為這是在運行時應(yīng)用它們的順序。

模式是一個作用于當(dāng)前 URL 的兼容 perl 的正則表達式,這里的“當(dāng)前”是指該規(guī)則生效時的 URL,它可能與被請求的 URL 不同,因為其他規(guī)則可能在此之前已經(jīng)發(fā)生匹配并對它做了改動。

下面是關(guān)于正則表達式格式的一些提示:

文本

  • .——匹配任何單個字符
  • [chars]——匹配當(dāng)前字符
  • [^chars]——不匹配當(dāng)前字符
  • text1|text2——匹配 text1 或 text2

量詞:

  • ?——零個或者 1 個 ? 號前的字符
  • *——零個或者 N 個 * 號前的字符(N > 0)
  • +——零個或 N 個 + 號前的字符(N > 1)

分組(text)——文本分組(設(shè)定第 N 組可以被引用為 RewriteRule)


行錨

^——匹配一行起始處的空字符串。
$——匹配一行結(jié)束處的空字符串。


轉(zhuǎn)義

\char ——將指定字符轉(zhuǎn)義(比如將.[]、() 等字符轉(zhuǎn)義)

要想了解更多關(guān)于正則表達式的信息,請參見 perl 正則表達式在線聯(lián)機手冊(perldoc perlre)。關(guān)于正則表達式及其變體(POSIX 正則表達式)的詳情,可看看這本書:

*Mastering Regular Expressions, 2nd Edition* (目前該書為第 3 版)
Jeffrey E.F. Friedl 
O'Reilly & Associates, Inc. 2002
ISBN 978-0-596-00289-3  

在規(guī)則中,NOT 字符(!)可作為模式的前綴,實現(xiàn)逆向模式。比如“如果當(dāng)前 URL 并匹配該模式”。這可以用在易于匹配的是逆向模式這種異常情況下,或者也可以作為最后一個默認(rèn)規(guī)則來使用。

注意:在使用 NOT 字符反轉(zhuǎn)模式時,不能在模式中包含分組的通配成分。這是因為,如果模式不匹配(比如反匹配),分組內(nèi)將沒有內(nèi)容。如果使用了逆向模式,就不能在替代字符串中使用 $N。

重寫規(guī)則中的替代字符串(substitution string)是一種用來取代模式匹配的原始 URL 的字符串。除了純文本之外,它還包括:

  1. 反向引用($N)RewriteRule 模式。
  2. 反向引用(%N)最后匹配的 RewriteCond 模式。
  3. 規(guī)則條件測試字符串中(%{VARNAME})的服務(wù)器變量。
  4. 映射函數(shù)調(diào)用(${mapname:key|default})。

反向引用表示的是形式 $N(N 的范圍為 0-9),它是指用模式所匹配的第 N 組的內(nèi)容去替換 URL。服務(wù)器變量 RewriteCond 指令的 TestString 所用的相同。映射函數(shù)來自 RewriteMap 指令。這 3 類變量都按照上述順序展開。

如前所述,所有的重寫規(guī)則都應(yīng)用于替代字符串(按照配置文件中所定義的順序)。URL 完全由替代字符串所替換,直到所有規(guī)則都應(yīng)用完畢,重寫過程才結(jié)束(或利用 L 標(biāo)記來終止)。

還有一個特殊的替代字符串:-,意思是不替代,當(dāng)需要讓重寫規(guī)則只匹配 URL 而不替換時,就用得上它了。這一字符串通常與 C(chain)標(biāo)記配合使用,為的是在替換發(fā)生前應(yīng)用多個模式。

另外,還可以將 [flags] 做為 RewriteRule 的第三個參數(shù),從而為替代字符串設(shè)置特殊標(biāo)記。flags是一個包含下列標(biāo)記且標(biāo)記間以逗號分隔的列表:

  • chain|C (與下一個規(guī)則相鏈接)

此標(biāo)記使當(dāng)前規(guī)則與下一個規(guī)則(它又可以與其后規(guī)則相鏈接,如此反復(fù))相鏈接。 它產(chǎn)生如下效果:如果某個規(guī)則被匹配,通常會繼續(xù)處理其后繼規(guī)則,這個標(biāo)記就不起作用;如果某規(guī)則不被匹配,則其后繼鏈接規(guī)將會被忽略。比如,在執(zhí)行一個外部重定向時, 對一個目錄級規(guī)則集,你可能需要刪除 .www(因為此處不應(yīng)該出現(xiàn) .www)。

  • cookie|CO = NAME:VAL:domain[:lifetime[:path]] (設(shè)置 cookie)

在客戶端瀏覽器上設(shè)置一個 cookie。cookie 的名稱是 NAME,其值是 VALdomain 字段是該 cookie 的域,比如 .apache.org,可選的lifetime 是 cookie 生命周期(以分鐘計),可選的 path 是 cookie 的路徑。

  • env|E = VAR:VAL (設(shè)置環(huán)境變量)

強制一個名為 VAR 的請求變量值為 VAL,VAL可以包含可擴展的反向引用的正則表達式 $N%N??梢远啻问褂迷摌?biāo)記,以便設(shè)置多個變量。

  • forbidden|F(強制禁止訪問該 URL )

強制禁止訪問當(dāng)前的 URL——立即反饋一個 HTTP 響應(yīng)代碼 403。使用這個標(biāo)記,可以鏈接若干 RewriteConds 以阻斷某些 URL。

  • gone|G(強制 URL 為已失效)

強制當(dāng)前 URL 為已失效——立即反饋一個 HTTP 響應(yīng)代碼 410(請求資源已被刪除)。使用這個標(biāo)記,可以標(biāo)明頁面已被刪除而不存在.

  • host|H=Host(重寫虛擬主機)
    重寫虛擬主機,而不是重寫 URL。

  • last|L(最后一個規(guī)則)

立即停止重寫操作,并不再應(yīng)用其他重寫規(guī)則。它對應(yīng)于 Perl 中的 last 命令或 C 語言中的 break 命令。使用該標(biāo)記可以防止當(dāng)前已被重寫的 URL 被后續(xù)規(guī)則所繼續(xù)重寫。比如,用它可以將根路徑的 URL(/)重寫為實際存在的 URL,比如:/e/www/。

  • next|N(重新執(zhí)行)

重新執(zhí)行重寫操作(從第一個重寫規(guī)則重新開始)。這時,要匹配的 URL 已不是原始 URL 了,而是經(jīng)最后一個重寫規(guī)則處理過的 URL。它對應(yīng)于 Perl 中的 next 命令或 C 語言中的 continue 命令。此標(biāo)記可以重新開始重寫操作,立即回到循環(huán)的頭部。

但是要小心,不要制造死循環(huán)!

  • nocase|NC(不區(qū)分大小寫)

使模式不區(qū)分大小寫。當(dāng)模式與當(dāng)前 URL 匹配時,A-Z 和 a-z 沒有區(qū)別。

  • noescape|NE(在輸出中不對 URI 進行轉(zhuǎn)義)

此標(biāo)記阻止重寫 Valve 對重寫結(jié)果應(yīng)用常規(guī)的 URI 轉(zhuǎn)義規(guī)則。一般情況下,特殊字符(如%、$;等)都會被轉(zhuǎn)義為十六進制值。此標(biāo)記可以阻止這種轉(zhuǎn)義,允許百分號等符號出現(xiàn)在輸出中,如:

RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]

/foo/zed 轉(zhuǎn)化為 /bar?arg=P1=zed 的安全請求。

  • qsappend|QSA(附加查詢串)

該標(biāo)記會強制重寫引擎將替代字符串中的一個查詢字符串部分添加到已有字符串上,而不是簡單地替換已有字符串。當(dāng)你想要通過重寫規(guī)則為查詢字符串添加更多數(shù)據(jù)時,可以使用該標(biāo)記。

  • redirect|R[=code](強制重定向)

http://thishost[:thisport]/(使新的 URL 成為一個 URI)作為替代字符串的前綴,從而強制執(zhí)行一個外部重定向。如果沒有指定 code,則產(chǎn)生一個HTTP 響應(yīng)代碼 302(暫時移動)。如果需要使用在 300-400 范圍內(nèi)的其他響應(yīng)代碼,只需在此指定這個數(shù)值即可。另外,還可以使用下列符號名稱:temp(默認(rèn)),permanent、seeother。用它可以把規(guī)范化的 URL 反饋給客戶端,如重寫 /~/u/,或?qū)?code>/u/user 加上斜杠,等等。

注意:在使用這個標(biāo)記時,必須確保替換字段是一個有效的 URL!否則它會指向一個無效的位置!并且要記住,此標(biāo)記本身只是對 URL 加上 http://thishost[:thisport]/ 前綴而已,不會妨礙重寫操作。通常,你會希望停止重寫,然后立即重定向。要想停止重寫,你還需要添加 L 標(biāo)記。

  • skip|S=num(忽略后續(xù)規(guī)則)

如果當(dāng)前規(guī)則匹配,此標(biāo)記會強制重寫引擎跳過當(dāng)前匹配規(guī)則后面的 num 個規(guī)則。它可以實現(xiàn)一個類似 if-then-else 的構(gòu)造:then 子句的最后一個規(guī)則是 skip = N,其中 N 代表 else 子句中的規(guī)則數(shù)目。(該標(biāo)記不同于chain|C 標(biāo)記?。?/p>

  • type|T=MIME-type(強制指定 MIME 類型)

強制指定目標(biāo)文件的 MIME 類型為 MIME-type,可基于一些條件設(shè)置內(nèi)容類型。比如在下面的代碼段中,如果利用 .phps 擴展調(diào)用 .php 文件,它們就能被 mod_php 模塊顯示。

RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]