Apache環境變數


有兩種環境變數會影響Apache HTTP Server。

首先,存在由底層作業系統控制的環境變數。這些是在伺服器啟動之前設定的。它們可以在組態檔案的擴充套件中使用,也可以使用PassEnv指令傳遞給CGI指令碼和SSI。

其次,Apache HTTP Server提供了一種機制,用於在命名變數中儲存資訊,這些變數也稱為環境變數。此資訊可用於控制各種操作,如紀錄檔記錄或存取控制。變數還用作與外部程式(如CGI指令碼)通訊的機制。本文將討論了操作和使用這些變數的不同方法。

儘管這些變數稱為環境變數,但它們與底層作業系統控制的環境變數不同。相反,這些變數在內部Apache結構中儲存和操作。它們僅在提供給CGI指令碼和伺服器端包含指令碼時才成為實際的作業系統環境變數。如果您希望操作伺服器本身執行的作業系統環境,則必須使用作業系統shell提供的標準環境操作機制。

設定環境變數

基本環境操作

在Apache中設定環境變數的最基本方法是使用無條件的SetEnv指令。也可以使用PassEnv指令從啟動伺服器的shell環境傳遞變數。

有條件的每請求設定

為了提高靈活性,mod_setenvif提供的指令允許在每個請求的基礎上設定環境變數,具體取決於特定請求的特徵。例如,只有在特定瀏覽器(使用者代理)發出請求時,或者僅在找到特定的Referer [sic]檔頭時才能設定變數。通過mod_rewriteRewriteRule可以獲得更大的靈活性,它使用[E = ...]選項來設定環境變數。

唯一識別符號
最後,mod_unique_id將每個請求的環境變數UNIQUE_ID設定為一個值,該值在非常特定的條件下保證在「所有」請求中是唯一的。

標準CGI變數

除了在Apache組態中設定並從shell傳遞的所有環境變數之外,CGI指令碼和SSI頁面還提供了一組環境變數,其中包含有關CGI規範所要求的請求的元資訊。

一些警告

  • 使用環境操作指令無法覆蓋或更改標準CGI變數。
  • suexec用於啟動CGI指令碼時,在啟動CGI指令碼之前,環境將被清除為一組安全變數。安全變數列表在suexec.c中的編譯時定義。
  • 出於可移植性的原因,環境變數的名稱可能只包含字母,數位和下劃線字元。另外,第一個字元可能不是數位。傳遞給CGI指令碼和SSI頁面時,與此限制不匹配的字元將被下劃線替換。
  • 一個特殊情況是HTTP檔頭,它通過環境變數傳遞給CGI指令碼等(見下文)。它們被轉換為大寫,只有短劃線被替換為下劃線;如果檔頭包含任何其他(無效)字元,則會以靜默方式刪除整個檔頭。
  • SetEnv指令在請求處理期間執行較晚,這意味著SetEnvIfRewriteCond等指令不會看到使用它設定的變數。
  • 當伺服器通過內部子請求查詢路徑(例如查詢DirectoryIndex或使用mod_autoindex生成目錄列表)時,子請求中不會繼承每個請求的環境變數。此外,由於mod_setenvif採取行動的API階段,因此不會在子請求中單獨評估SetEnvIf指令。

使用環境變數

CGI指令碼
環境變數的主要用途之一是將資訊傳遞給CGI指令碼。如上所述,除了在Apache組態中設定的任何變數之外,傳遞給CGI指令碼的環境還包括有關請求的標準元資訊。

SSI頁面

mod_include的INCLUDES過濾器處理的伺服器解析(SSI)文件可以使用echo元素列印環境變數,並且可以使用流控制元素中的環境變數來使頁面的某些部分以請求的特徵為條件。如上所述,Apache還為SSI頁面提供標準CGI環境變數。有關更多詳細資訊,請參閱SSI教學。

存取控制
可以使用env=ennyenv=directive中的deny,根據環境變數的值來控制對伺服器的存取。與SetEnvIf結合使用,可以根據用戶端的特性靈活控制對伺服器的存取。例如,可以使用這些指令拒絕存取特定瀏覽器(User-Agent)。

條件記錄
可以使用LogFormat選項%e在存取紀錄檔中記錄環境變數。此外,可以使用CustomLog指令的條件形式基於環境變數的狀態來決定是否記錄請求。與SetEnvIf結合使用,可以靈活控制記錄哪些請求。例如,您可以選擇不記錄以gif結尾的檔案名請求,也可以選擇僅記錄來自子網外的用戶端的請求。

條件響應檔頭
Header指令可以使用環境變數的存在或不存在來確定是否將某個HTTP檔頭放置在對用戶端的響應中。例如,這允許僅在來自用戶端的請求中接收到對應的報頭時才傳送特定的響應報頭。

外部過濾器啟用
mod_ext_filter使用ExtFilterDefine指令組態的外部過濾器可以使用disableenv =enableenv =選項啟用環境變數的條件。

URL重寫
RewriteCond中的%{ENV:variable}形式的TestString允許mod_rewrite的重寫引擎根據環境變數做出決策。請注意,沒有ENV:字首的mod_rewrite中可存取的變數實際上不是環境變數。相反,它們是mod_rewrite特有的變數,無法從其他模組存取。

特殊用途環境變數

互操作性問題導致引入了修改Apache與特定用戶端溝通時的行為方式。為了使這些機制盡可能靈活,可以通過定義環境變數來呼叫它們,通常使用BrowserMatch,例如也可以使用SetEnvPassEnv

downgrade-1.0
這會強制將請求視為HTTP/1.0請求,即使它是在後來的方言中。

force-gzip

如果啟用了DEFLATE過濾器,則此環境變數將忽略瀏覽器的accept-encoding設定,並將無條件地傳送壓縮輸出。

force-no-vary
這會導致在將響應檔頭傳送回用戶端之前從響應檔頭中刪除任何Vary欄位。有些客戶沒有正確解釋這個欄位; 設定此變數可以解決此問題。設定此變數還暗含著force-response-1.0

force-response-1.0
這會強制對發出HTTP/1.0請求的用戶端發出HTTP/1.0響應。它最初是由於AOL的代理問題而實現的。給定HTTP/1.1響應時,某些HTTP/1.0用戶端可能無法正常執行,這可用於與它們進行互操作。

gzip-only-text/html
設定為值1時,此變數將禁用mod_deflatetext/html以外的內容型別提供的DEFLATE輸出過濾器。如果願意使用靜態壓縮檔案,mod_negotiation也會評估變數(不僅適用於gzip,還適用於所有與「identity」不同的編碼)。

no-gzip
設定後,mod_deflateDEFLATE過濾器將關閉,mod_negotiation將拒絕提供編碼資源。

no-cache
適用於Apache-2.2.12及更高版本。設定後,mod_cache將不會儲存其他可快取的響應。此環境變數不會影響是否將為當前請求提供快取中已有的響應。

nokeepalive
這會在設定時禁用KeepAlive

prefer-language
這會影響mod_negotiation的行為。如果它包含語言標記(例如en,ja或x-klingon),則mod_negotiation會嘗試使用該語言提供變體。如果沒有這樣的變體,則適用正常的協商過程。

redirect-carefully
這會強制伺服器在向用戶端傳送重定向時更加小心。這通常在用戶端處理重定向的已知問題時使用。這最初是由於Microsoft WebFolders軟體出現問題而導致的,該軟體在通過DAV方法處理目錄資源上的重定向時遇到問題。

suppress-error-charset

適用於2.0.54之後的版本。
當Apache發出重定向以響應用戶端請求時,響應包括一些實際文字,以防用戶端無法(或不自動)遵循重定向。Apache通常根據它使用的字元集標記此文字,即ISO-8859-1

但是,如果重定向是使用不同字元集的頁面,則某些損壞的瀏覽器版本將嘗試使用重定向文字中的字元集而不是實際頁面。例如,這可能導致希臘語被錯誤地渲染。

設定此環境變數會導致Apache省略重定向文字的字元集,然後這些損壞的瀏覽器將正確使用目標頁面的字元集。

範例

將損壞的標題傳遞給CGI指令碼
從Apache 2.4開始,Apache對於如何在mod_cgi和其他模組中將HTTP檔頭轉換為環境變數更為嚴格:以前,檔頭名稱中的任何無效字元都只是轉換為下劃線。這允許通過檔頭注入進行一些潛在的跨站點指令碼攻擊(參見Unusual Web Bugs,slide 19/20)。

如果您必須支援傳送損壞的檔頭且無法修復的用戶端,則涉及mod_setenvifmod_headers的簡單解決方法用於仍然接受這些檔頭:

# 
# The following works around a client sending a broken Accept_Encoding
# header.
#
SetEnvIfNoCase ^Accept.Encoding$ ^(.*)$ fix_accept_encoding=$1
RequestHeader set Accept-Encoding %{fix_accept_encoding}e env=fix_accept_encoding

改變行為不端的用戶端的協定行為

早期版本建議在httpd.conf中包含以下行以處理已知的用戶端問題。由於不再能夠看到受影響的用戶端,因此不再需要此組態。

#
# The following directives modify normal HTTP response behavior.
# The first directive disables keepalive for Netscape 2.x and browsers that
# spoof it. There are known problems with these browser implementations.
# The second directive is for Microsoft Internet Explorer 4.0b2
# which has a broken HTTP/1.1 implementation and does not properly
# support keepalive when it is used on 301 or 302 (redirect) responses.
#
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0

#
# The following directive disables HTTP/1.1 responses to browsers which
# are in violation of the HTTP/1.0 spec by not being able to understand a
# basic 1.1 response.
#
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0

不需要在存取紀錄檔中記錄影象請求

此範例使影象請求不會出現在存取紀錄檔中。可以輕鬆修改它以防止記錄特定目錄,或防止記錄來自特定主機的請求。

SetEnvIf Request_URI \.gif image-request
SetEnvIf Request_URI \.jpg image-request
SetEnvIf Request_URI \.png image-request
CustomLog logs/access_log common env=!image-request

防止圖片盜鏈
此範例說明如何防止伺服器上的人員將伺服器上的影象用作其頁面上的內嵌影象。這不是推薦的組態,但它可以在有限的情況下工作。我們假設您的所有影象都位於名為/web/images的目錄中。

SetEnvIf Referer "^http://www\.example\.com/" local_referal
# Allow browsers that do not send Referer info
SetEnvIf Referer "^$" local_referal
<Directory "/web/images">
    Require env local_referal
</Directory>