有兩種環境變數會影響Apache HTTP Server。
首先,存在由底層操作系統控制的環境變數。這些是在伺服器啟動之前設置的。它們可以在配置檔的擴展中使用,也可以使用PassEnv
指令傳遞給CGI腳本和SSI。
其次,Apache HTTP Server提供了一種機制,用於在命名變數中存儲資訊,這些變數也稱為環境變數。此信息可用於控制各種操作,如日誌記錄或訪問控制。變數還用作與外部程式(如CGI腳本)通信的機制。本文將討論了操作和使用這些變數的不同方法。
儘管這些變數稱為環境變數,但它們與底層操作系統控制的環境變數不同。相反,這些變數在內部Apache結構中存儲和操作。它們僅在提供給CGI腳本和服務器端包含腳本時才成為實際的操作系統環境變數。如果您希望操作伺服器本身運行的操作系統環境,則必須使用操作系統shell提供的標準環境操作機制。
設置環境變數
基本環境操作
在Apache中設置環境變數的最基本方法是使用無條件的SetEnv
指令。也可以使用PassEnv
指令從啟動伺服器的shell環境傳遞變數。
有條件的每請求設置
為了提高靈活性,mod_setenvif
提供的指令允許在每個請求的基礎上設置環境變數,具體取決於特定請求的特徵。例如,只有在特定流覽器(用戶代理)發出請求時,或者僅在找到特定的Referer [sic]
標頭時才能設置變數。通過mod_rewrite
的RewriteRule
可以獲得更大的靈活性,它使用[E = ...]
選項來設置環境變數。
唯一識別字
最後,mod_unique_id
將每個請求的環境變數UNIQUE_ID
設置為一個值,該值在非常特定的條件下保證在“所有”請求中是唯一的。
標準CGI變數
除了在Apache配置中設置並從shell傳遞的所有環境變數之外,CGI腳本和SSI頁面還提供了一組環境變數,其中包含有關CGI規範所要求的請求的元資訊。
一些警告
- 使用環境操作指令無法覆蓋或更改標準CGI變數。
- 當
suexec
用於啟動CGI腳本時,在啟動CGI腳本之前,環境將被清除為一組安全變數。安全變數列表在suexec.c
中的編譯時定義。 - 出於可移植性的原因,環境變數的名稱可能只包含字母,數字和下劃線字元。另外,第一個字元可能不是數字。傳遞給CGI腳本和SSI頁面時,與此限制不匹配的字元將被下劃線替換。
- 一個特殊情況是HTTP標頭,它通過環境變數傳遞給CGI腳本等(見下文)。它們被轉換為大寫,只有短劃線被替換為下劃線;如果標頭包含任何其他(無效)字元,則會以靜默方式刪除整個標頭。
SetEnv
指令在請求處理期間運行較晚,這意味著SetEnvIf
和RewriteCond
等指令不會看到使用它設置的變數。- 當伺服器通過內部子請求查找路徑(例如查找
DirectoryIndex
或使用mod_autoindex
生成目錄列表)時,子請求中不會繼承每個請求的環境變數。此外,由於mod_setenvif
採取行動的API階段,因此不會在子請求中單獨評估SetEnvIf
指令。
使用環境變數
CGI腳本
環境變數的主要用途之一是將資訊傳遞給CGI腳本。如上所述,除了在Apache配置中設置的任何變數之外,傳遞給CGI腳本的環境還包括有關請求的標準元資訊。
SSI頁面
由mod_include
的INCLUDES篩檢程式處理的伺服器解析(SSI)文檔可以使用echo元素列印環境變數,並且可以使用流控制元素中的環境變數來使頁面的某些部分以請求的特徵為條件。如上所述,Apache還為SSI頁面提供標準CGI環境變數。有關更多詳細資訊,請參閱SSI教學。
訪問控制
可以使用env=enny
和env=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
,例如也可以使用SetEnv
和PassEnv
。
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_deflate
為text/html
以外的內容類型提供的DEFLATE
輸出篩檢程式。如果願意使用靜態壓縮檔,mod_negotiation
也會評估變數(不僅適用於gzip,還適用於所有與“identity”不同的編碼)。
no-gzip
設置後,mod_deflate
的DEFLATE
篩檢程式將關閉,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_cg
i和其他模組中將HTTP標頭轉換為環境變數更為嚴格:以前,標頭名稱中的任何無效字元都只是轉換為下劃線。這允許通過標頭注入進行一些潛在的跨站點腳本攻擊(參見Unusual Web Bugs,slide 19/20)。
如果您必須支持發送損壞的標頭且無法修復的客戶端,則涉及mod_setenvif
和mod_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>