什么是Referer?
Referer 是 HTTP 請求header
的一部分,當瀏覽器(或者模擬瀏覽器行為)向web
服務器發送請求的時候,頭信息里有包含 Referer 。比如我在www.sojson.com
里有一個www.baidu.com
鏈接,那么點擊這個www.baidu.com
,它的header
信息里就有:
Referer=https://www.sojson.com
由此可以看出來吧。它就是表示一個來源。看下圖的一個請求的 Referer 信息。
這里有一個小問題要說明下。
Referer 的正確英語拼法是referrer
。由於早期HTTP規范的拼寫錯誤,為了保持向后兼容就將錯就錯了。其它網絡技術的規范企圖修正此問題,使用正確拼法,所以目前拼法不統一。還有它第一個字母是大寫。
Referer的作用?
1.防盜鏈。
剛剛前面有提到一個小 Demo 。
我在www.sojson.com里有一個www.baidu.com
鏈接,那么點擊這個www.baidu.com
,它的header信息里就有:
Referer=https://www.sojson.com
那么可以利用這個來防止盜鏈了,比如我只允許我自己的網站訪問我自己的圖片服務器,那我的域名是www.sojson.com
,那么圖片服務器每次取到Referer來判斷一下是不是我自己的域名www.sojson.com
,如果是就繼續訪問,不是就攔截。
這是不是就達到防盜鏈的效果了?
2.防止惡意請求。
比如我的SOJSON網站上,靜態請求是*.html
結尾的,動態請求是*.shtml
,那么由此可以這么用,所有的*.shtml
請求,必須 Referer 為我自己的網站。
Referer=https://www.sojson.com
空Referer是怎么回事?什么情況下會出現Referer?
首先,我們對空 Referer 的定義為, Referer 頭部的內容為空,或者,一個 HTTP 請求中根本不包含 Referer 頭部。
那么什么時候 HTTP 請求會不包含 Referer 字段呢?根據Referer的定義,它的作用是指示一個請求是從哪里鏈接過來,那么當一個請求並不是由鏈接觸發產生的,那么自然也就不需要指定這個請求的鏈接來源。
比如,直接在瀏覽器的地址欄中輸入一個資源的URL地址,那么這種請求是不會包含 Referer 字段的,因為這是一個“憑空產生”的 HTTP 請求,並不是從一個地方鏈接過去的。
那么在防盜鏈設置中,允許空Referer和不允許空Referer有什么區別?
允許 Referer 為空,意味着你允許比如瀏覽器直接訪問,就是空。
如下圖:
這就是空的 Referer 。
拒絕空的 Referer 。比如我的www.sojson.com
的靜態資源都是拒絕空的Referer
的。如下圖,我訪問我的一個圖片。
看到了吧,直接拒絕訪問了,如果有同學在測試我網站的靜態資源的時候,記住強制刷新Ctrl + F5
,因為瀏覽器有緩存,可能你開始還是可以訪問的。
當然。這個你不能完全依賴 Referer 來做一些事情,因為這個最容易偽造來源。
每個語言,都可以,比如 Java 來模擬一個 Httpclient 請求。並且偽造來源。
/** * 從工信部獲取驗證碼 * @param session * @param response */ public static void getVCode(HttpSession session,HttpServletResponse response){ InputStream inputStream = null; ServletOutputStream outStream = null; try { //獲取登錄框的隱含參數 type="hidden" name="_xsrf" HttpClient client = new HttpClient(); client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"UTF-8"); client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); GetMethod method = new GetMethod("http://www.miitbeian.gov.cn/getVerifyCode"); method.setRequestHeader("Connection","close"); method.setRequestHeader("Host", "www.miitbeian.gov.cn"); method.setRequestHeader("Referer", "http://www.miitbeian.gov.cn/icp/publish/query/icpMemoInfo_showPage.action"); method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0"); // method.setRequestHeader("Cookie", (String)goon); client.executeMethod(method); Cookie[] cookies = client.getState().getCookies(); String sid = "",uid="",goon="__jsluid=%s; JSESSIONID=%s"; for (Cookie cookie : cookies) { String name = cookie.getName(); String value = cookie.getValue(); if("JSESSIONID".equals(name)){ sid = value; } if("__jsluid".equals(name)){ uid = value; } } goon = String.format(goon, uid,sid); //存儲工信部Session信息 session.setAttribute("goon", goon); inputStream= method.getResponseBodyAsStream(); //得到圖片的二進制數據,以二進制封裝得到數據,具有通用性 byte[] data = CacheFindManager.readInputStream(inputStream); outStream = response.getOutputStream(); outStream.write(data); outStream.flush() ; } catch (Exception e) { LoggerUtils.error(BeianGovManager.class, "獲取驗證碼出現異常。", e); }finally{ try { inputStream.close(); outStream.close(); } catch (IOException e) { LoggerUtils.error(BeianGovManager.class, "獲取驗證碼后,關閉流出現異常,請忽略!", e); } } }
好了,就這樣吧,有疑問,加群@soso,或者下面留言。知無不言言無不盡。