CsrfFilter是为了防御CSRF攻击的。CSRF攻击请参考松哥手把手教你在 SpringBoot 中防御 CSRF 攻击!so easy! 。
CsrfFilter的源码在要学就学透彻!Spring Security 中 CSRF 防御源码解析 说的很清楚了。
在这里是对LazyCsrfTokenRepository的使用做个总结。
CsrfFilter#doFilterInternal
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(HttpServletResponse.class.getName(), response);
CsrfToken csrfToken = this.tokenRepository.loadToken(request);
boolean missingToken = (csrfToken == null);
if (missingToken) {
csrfToken = this.tokenRepository.generateToken(request);
this.tokenRepository.saveToken(csrfToken, request, response);
}
request.setAttribute(CsrfToken.class.getName(), csrfToken);
request.setAttribute(csrfToken.getParameterName(), csrfToken);
if (!this.requireCsrfProtectionMatcher.matches(request)) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Did not protect against CSRF since request did not match "
+ this.requireCsrfProtectionMatcher);
}
filterChain.doFilter(request, response);
return;
}
String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
}
if (!equalsConstantTime(csrfToken.getToken(), actualToken)) {
this.logger.debug(
LogMessage.of(() -> "Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request)));
AccessDeniedException exception = (!missingToken) ? new InvalidCsrfTokenException(csrfToken, actualToken)
: new MissingCsrfTokenException(actualToken);
this.accessDeniedHandler.handle(request, response, exception);
return;
}
filterChain.doFilter(request, response);
}
在
if (missingToken) {
csrfToken = this.tokenRepository.generateToken(request);
this.tokenRepository.saveToken(csrfToken, request, response);
}
会生成csrf-token并保存,是get请求时,this.requireCsrfProtectionMatcher.matches(request)判断返回false,就不会走下面的csrf-token验证了。所以没有必要保存csrf-token。LazyCsrfTokenRepository对csrf-token做了代理只在需要保存时才保存。
LazyCsrfTokenRepository#saveToken
public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {
if (token == null) {
this.delegate.saveToken(token, request, response);
}
}
只有当token为null时才保存。一般情况下token都不会为null。
只有CsrfFilter#doFilterInternal调用到equalsConstantTime(csrfToken.getToken(), actualToken)验证csrf-token时,才去保存csrf-token。
SaveOnAccessCsrfToken#getToken()
public String getToken() {
saveTokenIfNecessary();
return this.delegate.getToken();
}
调用saveTokenIfNecessary去保存csrf-token。
标签:actualToken,CsrfFilter,request,SpringSecurity,csrfToken,token,csrf,过滤器,response From: https://www.cnblogs.com/shigongp/p/17320087.html