简介
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站
用处
1.页面统计
2.资源防盗链
缺点
Referer是不安全的,客户端可以通过设置改变 Request中的值,尽量不要用来进行安全验证等方面。
空的情形
下默认情况下Referer可能出现为空的场景:
1、页面从https跳转到http,应该是处于安全考虑,该点在RFC-2616中有说明,主流浏览器均遵守这个规则,比如IE、FF;但默认情况下https到https是会发送Referer的。
2、直接在浏览器中输入目标URL。
3、由于FF提供了很强大的自定义参数设置功能,所以我们可以通过about:config页面修改以下两个选项的默认设置:network.http.sendRefererHeader
(default=2),设置Referer的发送方式,0为完全不发送,1为只在点击链接时发送,在访问页面中的图像什么的时候不发送,2为始终发送。network.http.sendSecureXSiteReferrer
(default=true),设置从一个Https访问到另外Https页面的时候是否发送Referer,true为发送,false为不发送。
4、从收藏夹访问。
5、单击’主页’或者自定义的地址
6、用js来window.open等方式打开(还有location.href,location.replace())。
在PHP中可以通过预定义变量SERVER获取HTTP的Referer,即:_SERVER[‘HTTP_REFERER’]。
Apache利用HTTP_Referer防盗链
Apache利用HTTP_Referer防盗链
简单的,我们可以用HTTP请求header中的referer判断,只要referer是内部网站的地址或者可信任的地址,就可以访问相应资源。通过Apache的FilesMatch配置可以实现,在Apache的配置文件httpd.conf中加入:
SetEnvIfNoCase Referer “^http://www.example.com” local_ref=1
SetEnvIfNoCase Referer “^http://test.example.com” local_ref=1
<FilesMatch “\.(txt|doc|mp3|zip|rar|jpg|gif)”>
Order Allow,Deny
Allow from env=local_ref #referer为www.example.com或test.example.com的请求
Allow from 127.0.0.1 #本机地址
</FilesMatch>
其中SetEnvIf指令根据客户端的请求属性设置环境变量,SetEnvIfNoCase代表当满足某个条件时,为变量赋值,一般结合其他指令使用。
也可以使用正则表达式:
SetEnvIf Referer “^http://(.)+\.ilinux\.cn/” local_ref=1
SetEnvIf Referer “^http://(.)+\.isql\.cn/” local_ref=1
SetEnvIf Referer “^http://(.)+\.other\.org\.cn/” local_ref=1
SetEnvIf Request_URI “/logo(.)+” local_ref=0
<FilesMatch “\.(mp3|wmv|png|gif|jpg|jpeg|avi|bmp|ram|rmvb|rm|rar|zip|mp3)”>
Order Allow,Deny
Allow from env=local_ref
</FilesMatch>
SpringMvc中防盗链
public class SpringMVCInterceptor implements HandlerInterceptor {
/**
* preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在
* 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在
* Controller方法调用之前调用。SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返
* 回值为false,当preHandle的返回值为false的时候整个请求就结束了。
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
Iterator<String> key = request.getParameterMap().keySet().iterator();
String value = null;
while (key.hasNext()) {
value = request.getParameter(key.next());
if (value.indexOf(" AND ") > -1 || value.indexOf(" and ") > -1 || value.indexOf(" OR ") > -1 || value.indexOf(" or ") > -1) {
return false;
}
}
String referrer = request.getHeader("referer");
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
if(referrer==null||referrer.equals("")||referrer.lastIndexOf(basePath)==0){
return true;
}
else{
return false;
}
return true;
}
配置interceptors
<mvc:interceptors>
<bean class="com.kingnode.xsimple.filter.SpringMVCInterceptor"/>
</mvc:interceptors>