https://docs.spring.io/spring-security/reference/index.html
CSRF 공격이란?
Cross-Site Request Forgery
사이트 간 요청 위조의 줄임말.
웹 애플리케이션 취약점 중 하나로 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법이다.
중간에 CKEditor4가 끼게 되면 난이도가 부쩍 오른다.. (º﹃º )
직접 만든 폼에서 비동기 통신을 할 경우, 요청헤더 설정이 가능하기때문에 토큰을 함께 보내줄 수 있지만 이 경우 아직 해결법을 찾지 못했다. 이슈 사항은 아래와 같다.
< 일반적인 사용법 >
Security로 부터 정해진 HTML 태그에 CSRF 토큰을 전달 받음 ->
JS로 비동기 통신할 때 요청 헤더에 받은 토큰을 넣어 서버로 전달 ->
(토큰이 일치) 요청 수행 / (토큰이 불일치) 403 오류코드 반환
< CKEditor4에서의 사용법? >
Security로 부터 정해진 HTML 태그에 CSRF 토큰을 전달 받음 ->
HTML 하단의 <script>
에서 서버의 매핑 URL을 정해주면 알아서 요청 수행 ->
요청 헤더에 토큰을 설정할 수 없음
그래서 차선책으로, CKEditor4 이미지 업로드에 사용되는 URL만 CSRF 토큰 사용을 비활성화해두기로 했다. ..( ;ㅁ; )
따흑
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf()
.ignoringRequestMatchers("/boards/ck/imageUpload.do")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
... ;
return http.build();
}
이 경우, 직접 비동기 통신을 진행하므로 문제될 게 없다.
이전 포스팅에서 fetch API로 요청할 때 헤더에 넣을 내용을 변수로 분리했었다. 여기에 추가해준다.
//csrf token
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
//headers 에 csrfToken 설정
//json 타입
...
//multipart 타입
const multipartHeaders = {
};
multipartHeaders[csrfHeader] = csrfToken;
왜 이전처럼 Content-Type
을 multipart/form-data
로 명시하지 않냐면, 그렇게하면 403 오류
가 반환되기 때문이다.
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' ...
이유는 나도 모른다. security에서 인식이 안된다나 뭐라나. 어떤 분들은 web.xml
을 고치던데 안타깝게도 내 프로젝트에는 web.xml이 없다 ㅋㅠㅋ; 그래서 Content-Type을 명시하지 않는 방법을 사용했다. 이렇게 하면 또 작동한다. 마찬가지로 이유는 모르니까 묻지 마시길
< 참고 >
HTML 파일에서 태그는 아래와 같이 사용했다.
<input id="profile" name="profile" type="file">
보기엔 간단해 보이는데 왜 헤맸냐고?? 그것도.. 묻지마....짲응나니까