各瀏覽器對于以下各種非標(biāo)準(zhǔn) HTTP 報(bào)頭的兼容情況可以參考 Can I Use 站點(diǎn)上的相關(guān)內(nèi)容。
請求頭
DNT
請求某個(gè)網(wǎng)頁應(yīng)用程序停止跟蹤某個(gè)用戶。在 Firefox 瀏覽器中,相當(dāng)于 X-Do-Not-Track 協(xié)議頭字段(自 Firefox 4.0 測試(Beta)11 版開始支持)。 Safari 和 IE 9 也支持這個(gè)字段。
DNT: 1 (啟用)
DNT: 0 (禁用)
注:目前 DNT 在 W3C 還未正式成為標(biāo)準(zhǔn),參考:Tracking Preference Expression (DNT)
X-Forwarded-For
一個(gè)事實(shí)標(biāo)準(zhǔn),用于標(biāo)識某個(gè)通過超文本傳輸協(xié)議代理或負(fù)載均衡連接到某個(gè)網(wǎng)頁服務(wù)器的客戶端的原始互聯(lián)網(wǎng)地址。
X-Forwarded-For: client1, proxy1, proxy2
X-Forwarded-For: 129.78.138.66, 129.78.64.10
在 Java Servlet 中獲取客戶端 IP 地址的參考代碼:
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServletUtils {
private static final Logger log = LoggerFactory.getLogger( ServletUtils.class );
private static final String[] PROXY_REMOTE_IP_ADDRESS;
static {
// read2Array 將文件中的內(nèi)容讀出作為數(shù)組,
// 每個(gè)數(shù)組中的元素中文件中的一行,
// 若文件不存在時(shí)返回空數(shù)組
String[] proxyRemoteHeaders = read2Array( Thread.currentThread().getContextClassLoader() , "remote-ip-headers" );
if ( proxyRemoteHeaders.length == 0 ) {
proxyRemoteHeaders = read2Array( ServletUtils.class , "remote-ip-headers-default" );
}
PROXY_REMOTE_IP_ADDRESS = proxyRemoteHeaders;
log.info( "Remote address headers: {}" , Arrays.toString( PROXY_REMOTE_IP_ADDRESS ) );
}
/**
* 獲取請求的客戶端的 IP 地址。若應(yīng)用服務(wù)器前端配有反向代理的 Web 服務(wù)器,
* 需要在 Web 服務(wù)器中將客戶端原始請求的 IP 地址加入到 HTTP header 中。
*
* Web 服務(wù)器反向代理中用于存放客戶端原始 IP 地址的 Http header 名字,
* 默認(rèn)值為根據(jù)優(yōu)先級為 "X-Forwarded-For" 和 "X-Real-IP",
* 若有需要使用其他的 HTTP header,需要在 classpath 的 remote-ip-headers
* 文件中添加所需要的 HTTP header 名字,根據(jù)優(yōu)先級依次在該文件中增加數(shù)據(jù),
* 格式為每行一個(gè) headers 名稱。
*
* @param request HTTP 請求
* @return 遠(yuǎn)程客戶端的 IP 地址
*/
public static String getRemoteIp(HttpServletRequest request) {
for ( int i = 0; i < PROXY_REMOTE_IP_ADDRESS.length; i++ ) {
String ip = request.getHeader( PROXY_REMOTE_IP_ADDRESS[i] );
if ( StringUtils.isNotBlank(ip) ) {
return getRemoteIpFromForward( ip );
}
}
return request.getRemoteAddr();
}
/**
* 從 HTTP Header 中根據(jù)反向代理請求頭的規(guī)范截取客戶端連接 IP 地址。
* 如果經(jīng)過多次反向代理,在相應(yīng)的請求頭中獲得的是以“,<SP>”
* 分隔 IP 地址鏈,第一段則為客戶端 IP 地址。
*
* @param xforwardIp
* @return 通過代理服務(wù)器后獲取的客戶端 IP 地址
*/
private static String getRemoteIpFromForward(String xforwardIp) {
int commaOffset = xforwardIp.indexOf(',');
if (commaOffset < 0) {
return xforwardIp;
}
return xforwardIp.substring(0, commaOffset);
}
}
注:在 RFC 7239 中被 Forwarded 請求頭取代。
X-Forwarded-Host
一個(gè)事實(shí)標(biāo)準(zhǔn),用于請求客戶端原始 Host 的 HTTP 請求頭,由于經(jīng)過反向代理(負(fù)載均衡服務(wù)器)原始的 Host 值可能與實(shí)際值不同。
X-Forwarded-Host: en.wikipedia.org:80
X-Forwarded-Host: en.wikipedia.org
注:在 RFC 7239 中被 Forwarded 請求頭取代。
X-Forwarded-Proto
一個(gè)事實(shí)標(biāo)準(zhǔn),用于標(biāo)識某個(gè)超文本傳輸協(xié)議請求最初所使用的協(xié)議,因?yàn)?,在反向代理(?fù)載均衡)上,即使最初發(fā)往該反向代理的請求類型是安全的超文本傳輸協(xié)議(HTTPS),該反向代理也仍然可能會使用超文本傳輸協(xié)議(HTTP)來與網(wǎng)頁服務(wù)器通信。谷歌客戶端在與谷歌服務(wù)器通信時(shí)會使用該協(xié)議頭的一個(gè)替代形式(X-ProxyUser-Ip)。
X-Forwarded-Proto: https
注:在 RFC 7239 中被 Forwarded 請求頭取代。
X-Http-Method-Override
請求某個(gè)網(wǎng)頁應(yīng)用程序使用該協(xié)議頭字段中指定的方法(一般是 PUT 或 DELETE)來覆蓋掉在請求中所指定的方法(一般是 POST)。當(dāng)某個(gè)瀏覽器或防火墻阻止直接發(fā)送 PUT 或 DELETE 方法時(shí)(注意,這可能是因?yàn)檐浖械哪硞€(gè)漏洞,因而需要修復(fù),也可能是因?yàn)槟硞€(gè)配置選項(xiàng)就是如此要求的,因而不應(yīng)當(dāng)設(shè)法繞過),可使用這種方式。
X-HTTP-Method-Override: DELETE
在開發(fā) REST 風(fēng)格的 Web 服務(wù)時(shí),應(yīng)將 X-Http-Method-Override 考慮至實(shí)現(xiàn)中。在 Spring MVC 中有個(gè)通過 _method 請求參數(shù)實(shí)現(xiàn)的過濾器 HiddenHttpMethodFilter,可以參照這個(gè)過濾器去實(shí)現(xiàn)一個(gè)用于處理 X-Http-Method-Override 請求頭的過濾器。
X-Requested-With
主要用于標(biāo)識 Ajax 及可擴(kuò)展標(biāo)記語言請求。大部分的 JavaScript 框架會發(fā)送這個(gè)字段,且將其值設(shè)置為 XMLHttpRequest。
X-Requested-With: XMLHttpRequest
響應(yīng)頭
Timing-Allow-Origin
參考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin
用于指定特定站點(diǎn),以允許其訪問 Resource Timing API 提供的相關(guān)信息,否則這些信息會由于跨源限制將被報(bào)告為零。
Timing-Allow-Origin: *
Timing-Allow-Origin: <origin>[, <origin>]*
Strict-Transport-Security
一種 HSTS(HTTP Strict Transport Security, HTTP 嚴(yán)格傳輸安全)策略,強(qiáng)制客戶端(如瀏覽器)使用 HTTPS 與服務(wù)器創(chuàng)建連接。服務(wù)器開啟 HSTS 的方法是,當(dāng)客戶端通過 HTTPS 發(fā)出請求時(shí),在服務(wù)器返回的超文本傳輸協(xié)議響應(yīng)頭中包含 Strict-Transport-Security 字段。非加密傳輸時(shí)設(shè)置的 HSTS 字段無效。
比如,https://example.com/ 的響應(yīng)頭含有 Strict-Transport-Security: max-age=31536000; includeSubDomains。這意味著兩點(diǎn):
- 在接下來的一年(即 31536000 秒)中,瀏覽器只要向 example.com 或其子域名發(fā)送 HTTP 請求時(shí),必須采用 HTTPS 來發(fā)起連接。比如,用戶點(diǎn)擊超鏈接或在地址欄輸入 http://www.example.com/,瀏覽器應(yīng)當(dāng)自動將 http 轉(zhuǎn)寫成 https,然后直接向 https://www.example.com/ 發(fā)送請求。
- 在接下來的一年中,如果 example.com 服務(wù)器發(fā)送的 TLS 證書無效,用戶不能忽略瀏覽器警告繼續(xù)訪問網(wǎng)站。
Strict-Transport-Security: max-age=31536000; includeSubDomains
安全提示:若網(wǎng)站是 HTTPS 時(shí)應(yīng)設(shè)置該響應(yīng)頭,以避免通過 HTTP 發(fā)起請求后在服務(wù)器端進(jìn)行 302 跳轉(zhuǎn)至 HTTPS,這樣存在中間人攻擊潛在威脅,跳轉(zhuǎn)過程可能被惡意網(wǎng)站利用來直接接觸用戶信息,而不是原來的加密信息。更多的信息參考 MDN 中相關(guān)的內(nèi)容。
友情提示:一旦設(shè)置了 Strict-Transport-Security 頭后,在所設(shè)置的過期時(shí)間內(nèi)當(dāng)前域名就必須使用 HTTPS 協(xié)議進(jìn)行訪問,無法再通過 HTTP 訪問,如果還需要通過 HTTP 訪問只能更換域名(在服務(wù)端重定向至 HTTP 的新域名),使用時(shí)請注意。
注:已在 RFC 6797 中標(biāo)準(zhǔn)化。
X-Accel-Redirect
Nginx 后端響應(yīng)頭
參考:https://www.nginx.com/resources/wiki/start/topics/examples/x-accel
當(dāng)客戶端發(fā)起請求下載某個(gè)文件時(shí),因?yàn)椴]有 X-Accel-Redirect 頭,Web 服務(wù)器并不會立刻就把文件輸出給客戶端;而是將這個(gè)請求交給后端的程序語言,程序語言驗(yàn)證認(rèn)為該客戶端可以下載這個(gè)文件,就寫出相應(yīng)的 X-Accel-Redirect 頭并結(jié)束處理;X-Accel-Redirect 頭返回時(shí)經(jīng)過前端的 Web 服務(wù)器,Web 服務(wù)器檢查到這個(gè)頭之后,才把文件輸出到客戶端。
如果客戶端偽造一個(gè) X-Accel-Redirect 頭來讀取呢?當(dāng)然也是不能下載的,因?yàn)閣eb服務(wù)器只認(rèn)識后端發(fā)來的 X-Accel-Redirect 頭,客戶端發(fā)來的不算。
Nginx 還有很多 X-Accel 相關(guān)的參數(shù),比如速度、緩沖、字符集等,參考 Nginx 的 X-Accel 文檔。
X-Accel-Redirect: /mp3/1.mp3
X-Content-Type-Options
即使給一個(gè) html 文檔指定 Content-Type 為“text/plain”,在 IE8 中這個(gè)文檔依然會被當(dāng)做 HTML 來解析。利用瀏覽器的這個(gè)特性,攻擊者甚至可以讓原本應(yīng)該解析為圖片的請求被解析為 JavaScript。通過下面這個(gè)響應(yīng)頭可以禁用瀏覽器的類型猜測行為。這個(gè)響應(yīng)頭的值只能是 nosniff,可用于 IE8+ 和 Chrome。
X-Content-Type-Options: nosniff
X-Frame-Options
點(diǎn)擊劫持(Clickjacking)保護(hù)。
-
deny表示在 frame 中頁面不呈現(xiàn) -
sameorigin表示在 frame 中如果源地址不一致時(shí)頁面不呈現(xiàn) -
allow-from表示允許指定的地址 -
allowall非標(biāo)準(zhǔn),允許任一地址
X-Frame-Options: deny
注:已在 RFC 7034 中標(biāo)準(zhǔn)化。
X-XSS-Protection
參考:https://blogs.msdn.microsoft.com/ieinternals/2011/01/31/controlling-the-xss-filter/
跨站腳本攻擊 (XSS)過濾器,有以下幾種配置:
-
0禁用 XSS 保護(hù) -
1啟用 XSS 保護(hù) -
1; mode=block啟用 XSS 保護(hù),并在檢查到 XSS 攻擊時(shí),停止渲染頁面(例如 IE8 中,檢查到攻擊時(shí),整個(gè)頁面會被一個(gè) # 替換)
X-XSS-Protection: 1; mode=block
參考
- 一些安全相關(guān)的 HTTP 響應(yīng)頭, https://imququ.com/post/web-security-and-response-header.html
- Content Security Policy 介紹,https://imququ.com/post/content-security-policy-reference.html
- HTTP 頭字段列表,https://zh.wikipedia.org/wiki/HTTP%E5%A4%B4%E5%AD%97%E6%AE%B5%E5%88%97%E8%A1%A8
- List of HTTP header fields, https://en.wikipedia.org/wiki/List_of_HTTP_header_fields