问题:
**CSRF概念:**CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
- 首先用户C浏览并登录了受信任站点A;
- 登录信息验证通过以后,站点A会在返回给浏览器的信息中带上已登录的cookie,cookie信息会在浏览器端保存一定时间(根据服务端设置而定);
- 完成这一步以后,用户在没有登出(清除站点A的cookie)站点A的情况下,访问恶意站点B;
- 这时恶意站点 B的某个页面向站点A发起请求,而这个请求会带上浏览器端所保存的站点 A 的cookie;
- 站点A根据请求所带的 cookie,判断此请求为用户C所发送的。
因此,站点A会报据用户C的权限来处理恶意站点B所发起的请求,而这个请求可能以用户C的身份发送 邮件、短信、消息,以及进行转账支付等操作,这样恶意站点B就达到了伪造用户C请求站点 A的目的。
受害者只需要做下面两件事情,攻击者就能够完成CSRF攻击:
- 登录受信任站点 A,并在本地生成cookie;
- 在不登出站点A(清除站点A的cookie)的情况下,访问恶意站点B。
通过Referer识别 进行CSRF防御
在springboot项目中 ,通过增加拦截器,识别refer 即可防御csrf 攻击。配置自己信任的白名单“Referer”
新建拦截器配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private RefererInterceptor refererInterceptor;
/**
* 添加过滤器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(refererInterceptor).addPathPatterns("/**").excludePathPatterns("/", "/login", "/logout");
}
@Bean
public RefererInterceptor getInterceptor() {
return new RefererInterceptor();
}
}
新建拦截器
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
@Component
public class RefererInterceptor extends HandlerInterceptorAdapter {
/**
* 白名单
*/
private String[] refererDomain = new String[]{"www.baidu.com","xxx.xxx.xx"};
/**
* 是否开启referer校验
*/
private Boolean check =true;
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
if (!check) {
return true;
}
String referer = req.getHeader("referer");
String host = req.getServerName();
// 验证非get请求
if (!"GET".equals(req.getMethod())) {
if (referer == null) {
// 状态置为404
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return false;
}
java.net.URL url = null;
try {
url = new java.net.URL(referer);
} catch (MalformedURLException e) {
// URL解析异常,也置为404
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return false;
}
// 首先判断请求域名和referer域名是否相同
if (!host.equals(url.getHost())) {
// 如果不等,判断是否在白名单中
if (refererDomain != null) {
for (String s : refererDomain) {
if (s.equals(url.getHost())) {
return true;
}
}
}
return false;
}
}
return true;
}
}
参考:
https://blog.csdn.net/junmoxi/article/details/89208311
转载:https://blog.csdn.net/u012373815/article/details/102488687
查看评论