当然也可以这么写,可以看后续对默认的 DefaultRequiresCsrfMatcher 的源码
public class CsrfSecurityRequestMatcher implements RequestMatcher {private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("^/rest/.*", null);@Overridepublic boolean matches(HttpServletRequest request) {if(allowedMethods.matcher(request.getMethod()).matches()){return false;}return !unprotectedMatcher.matches(request);}}
Spring Security - CookieCsrfTokenRepository如何工作的呢?CookieCsrfTokenRepository.withHttpOnlyFalse() 本质就是 new CookieCsrfTokenRepository()
public static CookieCsrfTokenRepository withHttpOnlyFalse() {CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();result.setCookieHttpOnly(false);return result;}
为何默认的存放CSRFToken的cookie是httpOnly呢?如果cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,窃取cookie内容,这样就增加了cookie的安全性,即便是这样,也不要将重要信息存入cookie 。XSS全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性 。其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的 。如,盗取用户Cookie、破坏页面结构、重定向到其它网站等 。
【CSRF 详解:攻击,防御,Spring Security应用等】// 比如,设置https的cookieresponse.addHeader("Set-Cookie", "uid=112; Path=/; Secure; HttpOnly");
Cookie CsrfToken 默认的封装static final String DEFAULT_CSRF_COOKIE_NAME = "XSRF-TOKEN";static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN";private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;private String headerName = DEFAULT_CSRF_HEADER_NAME;private String cookieName = DEFAULT_CSRF_COOKIE_NAME;@Overridepublic CsrfToken generateToken(HttpServletRequest request) {return new DefaultCsrfToken(this.headerName, this.parameterName,createNewToken());}
CsrfToken的保存@Overridepublic void saveToken(CsrfToken token, HttpServletRequest request,HttpServletResponse response) {String tokenValue = https://www.isolves.com/it/aq/wl/2020-01-08/token == null ? "" : token.getToken();Cookie cookie = new Cookie(this.cookieName, tokenValue);cookie.setSecure(request.isSecure());if (this.cookiePath != null && !this.cookiePath.isEmpty()) {cookie.setPath(this.cookiePath);} else {cookie.setPath(this.getRequestContext(request));}if (token == null) {cookie.setMaxAge(0);}else {cookie.setMaxAge(-1);}if (cookieHttpOnly && setHttpOnlyMethod != null) {ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);}response.addCookie(cookie);}
CsrfToken的加载@Overridepublic CsrfToken loadToken(HttpServletRequest request) {Cookie cookie = WebUtils.getCookie(request, this.cookieName);if (cookie == null) {return null;}String token = cookie.getValue();if (!StringUtils.hasLength(token)) {return null;}return new DefaultCsrfToken(this.headerName, this.parameterName, token);}
Spring Security - CsrfFilter是如何完成拦截和校验的呢?public final class CsrfFilter extends OncePerRequestFilter {// 负责CsrfToken生成,加载等private final CsrfTokenRepository tokenRepository;// 负责拦截Csrf的匹配private RequestMatcher requireCsrfProtectionMatcher = DEFAULT_CSRF_MATCHER;// 被拦截后的拒绝策略private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();// CsrfFilter的过滤逻辑@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {request.setAttribute(HttpServletResponse.class.getName(), response);// 加载token,没有的自动生成一个CsrfToken csrfToken = this.tokenRepository.loadToken(request);final 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)) {filterChain.doFilter(request, response);return;}// 校验tokenString actualToken = request.getHeader(csrfToken.getHeaderName());if (actualToken == null) {actualToken = request.getParameter(csrfToken.getParameterName());}if (!csrfToken.getToken().equals(actualToken)) {if (this.logger.isDebugEnabled()) {this.logger.debug("Invalid CSRF token found for "+ UrlUtils.buildFullRequestUrl(request));}if (missingToken) {this.accessDeniedHandler.handle(request, response,new MissingCsrfTokenException(actualToken));}else {this.accessDeniedHandler.handle(request, response,new InvalidCsrfTokenException(csrfToken, actualToken));}return;}filterChain.doFilter(request, response);}}
推荐阅读
- Redis两种持久化机制RDB和AOF详解
- 穿山甲有攻击性吗 穿山甲的爪子为什么可以穿山?
- 李晓明工笔《双清白头》步骤详解 李晓明工笔画教程
- 大黑客必知必会的xxe攻击漏洞,带你了解黑客的世界
- 详解Oracle行列转换函数--pivot函数和unpivot函数
- 详解网站推广中论坛推广的技巧
- XSS的两种攻击原理及五种防御方式
- 汽车胎压不同季节的调整标准·详解
- 看netstat命令,如何用于判断服务器是否遭受DDoS攻击?
- Java虚拟机:Jvm概念和原理详解以及GC机制的分析