728x90

- 쇼핑몰 입장에서는 인증이 완료된 사용자의 쿠키가 있기 때문에 정상적인 인증이라고 생각한다.
CSRFFilter
- 모든 요청에 랜덤하게 생성된 토큰을 HTTP 파라미터로 요구
- 요청 시 전달되는 토큰 값과 서버에 저장된 실제 값과 비교한 후 만약 일치하지 않으면 요청은 실패한다
-
Client
-
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
-
HTTP 메소드 : PATCH, POST, PUT, DELETE
-
- Spring Security
-
http.csrf() : 기본 활성화되어 있음
-
http.csrfhttp.csrf(). disabled() : 비활성화
-
-
CSRFFilter@Override 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); } 
CSRF 기능 설정 - Thymeleaf와 같은 뷰 템플릿, Spring Form 태그를 사용하게 되면 기본으로 파라미터로 CSRF 토큰을 생성하여 준다.
728x90