Spring Boot - SpringDoc (Swagger) 설정
application.yml
1
2
3
4
5
springdoc:
show-login-endpoint: true
swagger-ui:
tags-sorter: alpha
groups-order: asc
springdoc.show-login-endpoint
- security login 사용시에 엔드포인트 노출 설정 (기본값: false)
- security login 사용시에 엔드포인트 노출 설정 (기본값: false)
springdoc.swagger-ui.tags-sorter
: tag 정렬 방법 설정- 또는
springdoc.swagger-ui.tagsSorter
- 설정 값:
alpha
, 사용자 정의 - 사용자 정의 정렬 구현 방법: yml에서 해당 옵션 설정하지 않고 java로 커스텀 정렬 구현 후 bean 등록
- java 작성 예시
1 2 3 4 5 6 7
@Bean public OpenApiCustomiser sortTagsAlphabetically() { return openApi -> openApi.setTags(openApi.getTags() .stream() .sorted(Comparator.comparing(tag -> StringUtils.stripAccents(tag.getName()))) .collect(Collectors.toList())); }
- java 작성 예시
- 또는
springdoc.swagger-ui.groups-order
: group 정렬 방법 설정- 또는
springdoc.swagger-ui.operationsSorter
- 설정 값:
alpha
,asc
,desc
,method
method
로 설정하면 http method (GET, POST, DELETE 등)으로 정렬
- 또는
java
기본 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
Info info = new Info()
.version("1.0")
.title("Simple Board 02 - User Service")
.description("""
📢 인증키 입력시 다음 형태로 입력해야 한다.
Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJnaW13bGd1c0BnbWFpbC5jb20iLCJpZCI6MywiZX
""");
// server url setting
Server server = new Server();
server.setUrl("http://localhost:8000/api/user"); // 이 주소에 end point 붙여 실행
// Authorize - jwt setting
String jwtKey = "x-token";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtKey);
Components components = new Components()
.addSecuritySchemes(jwtKey, new SecurityScheme()
.name(jwtKey)
.type(SecurityScheme.Type.APIKEY) // APIKEY, HTTP, OAUTH2, OPENIDCONNECT, MUTUALTLS
.scheme("bearer")
.bearerFormat("JWT") // JWT, OAuth 등
.in(SecurityScheme.In.HEADER)); // COOKIE, HEADER, QUERY
return new OpenAPI()
.info(info)
.components(components)
.addSecurityItem(securityRequirement)
.servers(List.of(server));
}
}
그룹 설정 - 기본
1. 특정 end-point를 하나의 그룹으로 묶음
1
2
3
4
5
6
7
8
9
10
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi signUpGroupedOpenApi() {
return GroupedOpenApi.builder()
.group("그룹 이름")
.pathsToMatch("/end/point/1", "/end-point/**")
.build();
}
}
2. 특정 end-point를 제외하고 하나의 그룹으로 묶음
1
2
3
4
5
6
7
8
9
10
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi signUpGroupedOpenApi() {
return GroupedOpenApi.builder()
.group("그룹 이름")
.pathsToExclude("/end/point/1", "/end-point/**")
.build();
}
}
그룹 설정 - security login 사용하는 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi memberGroupedOpenApi() {
return GroupedOpenApi.builder()
.group("2. 회원 API")
.pathsToExclude("/end/point/1", "/end-point/**")
.addOpenApiCustomizer(securityLoginEndpointCustomiser()) // 추가
.build();
}
}
// 커스텀 시큐리티 로그인 정보 반영
public OpenApiCustomizer securityLoginEndpointCustomiser() {
FilterChainProxy filterChainProxy = applicationContext.getBean(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, FilterChainProxy.class);
return openAPI -> {
for (SecurityFilterChain filterChain : filterChainProxy.getFilterChains()) {
Optional<AuthenticationFilter> optionalFilter =
filterChain.getFilters().stream()
.filter(AuthenticationFilter.class::isInstance)
.map(AuthenticationFilter.class::cast)
.findAny();
if (optionalFilter.isPresent()) {
AuthenticationFilter authenticationFilter = optionalFilter.get();
Operation operation = new Operation();
Schema<?> schema = new ObjectSchema()
.addProperty("email", new StringSchema())
.addProperty("password", new StringSchema());
String mediaType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
RequestBody requestBody = new RequestBody().required(true).content(new Content().addMediaType(mediaType, new MediaType().schema(schema)));
operation.requestBody(requestBody);
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse(String.valueOf(HttpStatus.OK.value()),new ApiResponse().description(HttpStatus.OK.getReasonPhrase()));
apiResponses.addApiResponse(String.valueOf(HttpStatus.FORBIDDEN.value()), new ApiResponse().description(HttpStatus.FORBIDDEN.getReasonPhrase()));
operation.responses(apiResponses);
operation.addTagsItem("1. 로그인");
operation.description("로그인 후 인증키는 header에서 `x-token` 확인");
PathItem pathItem = new PathItem().post(operation);
try {
Field requestMatcherField = AbstractAuthenticationProcessingFilter.class.getDeclaredField("requiresAuthenticationRequestMatcher");
requestMatcherField.setAccessible(true);
AntPathRequestMatcher requestMatcher = (AntPathRequestMatcher) requestMatcherField.get(authenticationFilter);
String loginPath = requestMatcher.getPattern();
requestMatcherField.setAccessible(false);
openAPI.getPaths().addPathItem(loginPath, pathItem);
}
catch (NoSuchFieldException | IllegalAccessException |
ClassCastException ignored) {
// Exception escaped
log.trace(ignored.getMessage());
}
}
}
};
}
}
securityLoginEndpointCustomiser()
메서드는 사용자 정의 security login 정보를 반영하기 위해org.springdoc.security.SpringDocSecurityConfiguration.SpringDocSecurityConfiguration#springSecurityLoginEndpointCustomiser
코드를 가져와서 수정
참고한 사이트
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.