[Spring Boot]Spring Security + Swagger 연동
RestAPI의 테스트를 위해 Swagger를 연동하면서 발생했던 에러들과 해결법 공유를 위해 포스팅을 남겨봅니다.
※테스트 환경
- Spring Boot : 2.7.2 (+Security)
- Swagger 3.0.0
* swagger 연동을 위한 config 설정은 아래에 작성해놓았습니다.
swagger 연동 후 아래와 같이 swagger-ui.html로 페이지 이동이 안되는 현상이 발생했습니다.
연동 실패한 2.9.2 버전
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
검색 결과 시큐리티 인증대상에서 제외시켜주면 된다고했지만 어째서인지 실패였습니다.
//swagger 인증 대상에서 제외
web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui",
"/swagger-resources", "/configuration/security",
"/swagger-ui.html", "/webjars/**","/swagger/**");
3.0.0 버전으로 업그레이드 후 다시 테스트해봤습니다.
3.0.0 버전으로 업그레이드를 할 때는 springfox-swagger2가 아닌 springfox-boot-starter 디펜던시를 주입하도록 되었습니다.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
이번엔 Failed to start bean 'documentationPluginsBootstrapper' 에러가 발생했습니다. 검색해보니 Spring boot 2.6버전 이후에 spring.mvc.pathmatch.matching-strategy 값이 ant_apth_matcher에서 path_pattern_parser로 변경되면서 몇몇 라이브러리(swagger포함)에 오류가 발생한다고 합니다.
application.properties 설정파일에 spring.mvc.pathmatch.matching-strategy=ant-path-matcher 옵션을 추가해주니 문제가 해결됐습니다.
연결 주소는 /swagger-ui/index.html 로 변경됐습니다. 아래 SecurityConfig와 같이 인증대상에서 Swagger 관련된 파일들을 제외하고 접속해보면 정상적으로 연결되는 것을 확인할 수 있습니다.
@Configuration
public class SwaggerConfig {
private static final String API_NAME = "WENAIL API";
private static final String API_VERSION = "1.0";
private static final String API_DESCRIPTION = "WENAIL API 명세서";
@Bean
public Docket api() {
@SuppressWarnings("deprecation")
Parameter parameterBuilder = new ParameterBuilder()
.name(HttpHeaders.AUTHORIZATION)
.description("Access Tocken")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
List<Parameter> globalParamters = new ArrayList<>();
globalParamters.add(parameterBuilder);
return new Docket(DocumentationType.SWAGGER_2)
.globalOperationParameters(globalParamters)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.app.wenail.rest"))
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(API_NAME)
.version(API_VERSION)
.description(API_DESCRIPTION)
.build();
}
}
SecurityConfig.java(Security 설정 일부)
@Override
public void configure(WebSecurity web) throws Exception {
//static 하위 파일은 인증 대상에서 제외
web.ignoring().antMatchers(
"/css/**",
"/fonts/**",
"/js/**",
"/images/**",
"/plugins/**/**");
web.ignoring().antMatchers("/favicon.ico");
//swagger 인증 대상에서 제외
web.ignoring().antMatchers(
"/v2/api-docs", "/configuration/ui", "/configuration/security",
"/webjars/**","/swagger/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("=====================:: WENAIL ::=====================");
logger.info(">> Run on Spring security");
logger.info("======================================================");
http.authorizeRequests()
//swagger
.antMatchers("/swagger-ui/**").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN", "MASTER")
.anyRequest().authenticated();
//로그인 설정
http.formLogin()
.loginPage("/login")
.loginProcessingUrl("/authenticate")
.failureUrl("/login?error=true")
.successHandler(customAuthenticationSuccessHandler)
.permitAll();
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login")
.invalidateHttpSession(true);
http.exceptionHandling()
.accessDeniedPage("/denied");
}