该拦截器基于SpringBoot工程,目的是防止跨站请求伪造漏洞,即csrf攻击
一、漏洞测试方法:
例如修改信息的请求为:
GET my?username=BOB&age=18 HTTP/1.1
Host: xxx.com
Referer: xxx.com/my
......
利用抓包工具,将修改信息的请求中的Referer: xxx.com/my
修改为其他内容,再次发送请求
GET my?username=BOB&age=18 HTTP/1.1
Host: xxx.com
Referer: xxx111.com
......
如果执行修改操作成功,即存在跨站请求伪造漏洞。同理,如果使用的是随机token,那么将token值改掉, 修改操作能够执行成功,如成功则存在漏洞。针对所有增删修改类操作接口。
二、防范方法
本方法仅做参考,具体如何防范可使用框架Spring Security或参考具体项目。
配置拦截器:
package com.shuyun.common.interceptor;
import com.shuyun.common.exception.CustomException;
import com.shuyun.common.utils.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 拦截器
*
* @author hanyang
* @date 2022-08-05
*/
public class RefererInterceptor extends HandlerInterceptorAdapter {
/**
* 配置需要进行判断的referer地址白名单
*/
private String[] urlList = {
//配置到域名即可
"https://xxx.xxx.xxx"
};
/**
* 拦截规则
*
* @param req
* @param resp
* @param handler
* @return
*/
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
// 从 HTTP 头中取得 Referer 值
String referer = req.getHeader("Referer");
System.out.println("referer--> " + referer);
// 判断 Referer 是否符合规则开头
if (StringUtils.isEmpty(referer)) {
System.out.println("执行正确referer");
return true;
} else if (StringUtils.isNotEmpty(referer)) {
if (isRightUrl(referer,urlList)){
return isRightUrl(referer,urlList);
}
throw new CustomException("跳转页面有风险,请稍后再试!");
} else {
//如果不是则抛异常
throw new CustomException("跳转页面有风险,请稍后再试!");
}
}
/**
* 判断请求的referer是否在配置的白名单中
*
* @author hanyang
* @date 2022-08-05
*/
public boolean isRightUrl(String referer, String[] urlList) {
//标识字符串,如果匹配添加0,不匹配添加1
StringBuilder flag = new StringBuilder();
String isMatching = "0";
String isNotMatching = "1";
for (String url : urlList) {
//如果referer匹配,则返回true
if (referer.trim().startsWith(url)) {
flag.append(isMatching);
}
//一旦有一个不匹配,则加入一个1
flag.append(isNotMatching);
}
//如果包含0,则说明有匹配值
if (flag.toString().contains(isMatching)) {
return true;
}
return false;
}
}
将拦截器注册到Spring中
package com.shuyun.common.config;
import com.shuyun.common.interceptor.RefererInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截器注册配置
*
* @author hanyang
* @date 2022-08-05
*/
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public RefererInterceptor refererInterceptor() {
return new RefererInterceptor();
}
/**
* 注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//referer拦截
registry.addInterceptor(refererInterceptor());
}
}
后续所有请求都会经过拦截器进行拦截,通过白名单校验则会放行,不通过则会抛异常