아직 남들에게 보여줄 만큼은 아니지만 혼자 나름대로 열심히 토이프로젝트를 진행하고 있는데, 아무래도 BackEnd 와 FrontEnd 를 분리해서 진행하려고 보니 테스트하는데에 불편함이 있습니다.
게다가 일반 회원 로그인 기능 없이 소셜 로그인으로만 Security 를 구현해놨더니 더더욱 REST API 만으로는 테스트가 힘들어서 뒤로 미뤄뒀던 Swagger 를 개발 초기 단계에서 적용하기로 했습니다.
1. build.gradle
에 dependency 추가
// open api 3.0 + swagger
implementation 'org.springdoc:springdoc-openapi-ui:1.5.8'
여기까지 추가하면 알아서 /v3/api-docs
와 /swagger-ui.html
이 자동으로 생성되기때문에 바로 확인할 수 있….긴한데
테스트를 해보니 POST 요청이 모두 Forbidden 으로 떨어지는 문제가 발생했다. 이는 Security 에 csrf 문제로 아래와 같이 해결할 수 있다.
2. SecurityConfig
특정 URL 요청(swagger)에만 csrf 를 비활성화 시킨다.
CsrfRequireMatcher.class
생성
public class CsrfRequireMatcher implements RequestMatcher {
private static final Pattern ALLOWED_METHODS = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
@Override
public boolean matches(HttpServletRequest request) {
if (ALLOWED_METHODS.matcher(request.getMethod()).matches())
return false;
final String referer = request.getHeader("Referer");
if (referer != null && referer.contains("/swagger-ui")) {
return false;
}
return true;
}
}
SecurityConfig
수정
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ...
@Override
protected void configure(HttpSecurity http) {
http.csrf().disable()
.authorizeRequests()
.antMatchers("swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**").hasRole(Role.USER.name())
// ...
;
http.csrf()
.requireCsrfProtectionMatcher(new CsrfRequireMatcher())
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
작성된 내용에 대한 지적은 환영입니다. 많이 알려주세요.
Reference
https://springdoc.org
https://www.baeldung.com/spring-rest-openapi-documentation
https://blog.jiniworld.me/83#a02-3