通过RefererInterceptor处理csrf攻击
一般网站是通过cookie存储客户凭证。当访问一个恶意网站,该网站在页面上构造了一个恶意的http请求,请求一个敏感的数据接口。而该请求会携带上你的cookie。对于服务器而言这是一次合法的请求。这就是csrf攻击。
防止csrf现在最多的方法就是,在渲染html页面的时候添加 csrt_token
,提交表单数据的时候,把该token
一起提交,在处理请求的时候校验该token的合法性。但是比较麻烦,需要生成。存储,验证等等步骤
比较简单的就是利用浏览器的:Referer
头
这个httpheader
会给服务端暴露,当前请求来自于哪个域名?有了这个信息,就可以判断当前的请求是否是csrf攻击请求。(图片等资源的防盗链也是用的它)
参考
RefererInterceptor
逻辑很简单,只需要把它添加到系统的拦截器链,并且设置需要拦截校验的路径就行
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
import java.net.URL;
public class RefererInterceptor extends HandlerInterceptorAdapter {
static final Logger LOGGER = LoggerFactory.getLogger(RefererInterceptor.class);
/**
* 允许请求的白名单域名
*/
static final String[] ALLOW_DOMAIN = new String[] {"www.springboot.io", "127.0.0.1"};
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 客户端的 referer 头
String referer = request.getHeader(HttpHeaders.REFERER);
if (StringUtils.isEmpty(referer)){
return true;
}
// 客户端请求的域名
String serverName = request.getServerName();
LOGGER.info("serverName={}, referer={}", serverName, referer);
try{
String refererHost = new URL(referer).getHost();
if (refererHost.equals(serverName)){
return true;
}
// 非同域的请求,判断是否在白名单中
for (String domain : ALLOW_DOMAIN){
if (domain.equalsIgnoreCase(refererHost)){
// 匹配到白名单域名
return true;
}
}
}catch (MalformedURLException malformedURLException){
}
/**
* 非法请求
*/
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return false;
}
}