Spring Boot 集成 Swagger2 很簡單,由於接口采用了OAuth2.0 & JWT 協議做了安全驗證,使用過程中也遇到了很多小的問題,多次嘗試下述配置可以正常使用。
Maven
<!-- swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-bean-validators</artifactId> <version>2.8.0</version> </dependency>
Swagger2Configuration
@Configuration
@EnableSwagger2
public class Swagger2Configuration {
// @Value("${config.oauth2.accessTokenUri}")
private String accessTokenUri ="http://localhost:8080/oauth/token";
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API 接口服務")
.description("API 接口服務")
.termsOfServiceUrl("http://www.cnblogs.com/irving")
.version("v1")
.license("Apache License Version 2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
.contact(new Contact("irving","http://www.cnblogs.com/irving","zhouyongtao@outlook.com"))
.build();
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.holiday.sunweb.controller"))
//.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build()
.securityContexts(Collections.singletonList(securityContext()))
.securitySchemes(Arrays.asList(securitySchema(), apiKey(), apiCookieKey()));
// .globalOperationParameters(
// newArrayList(new ParameterBuilder()
// .name("access_token")
// .description("AccessToken")
// .modelRef(new ModelRef("string"))
// .parameterType("query")
// .required(true)
// .build()));
}
@Bean
public SecurityScheme apiKey() {
return new ApiKey(HttpHeaders.AUTHORIZATION, "apiKey", "header");
}
@Bean
public SecurityScheme apiCookieKey() {
return new ApiKey(HttpHeaders.COOKIE, "apiKey", "cookie");
}
private OAuth securitySchema() {
List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("read", "read all"));
authorizationScopeList.add(new AuthorizationScope("write", "access all"));
List<GrantType> grantTypes = newArrayList();
GrantType passwordCredentialsGrant = new ResourceOwnerPasswordCredentialsGrant(accessTokenUri);
grantTypes.add(passwordCredentialsGrant);
return new OAuth("oauth2", authorizationScopeList, grantTypes);
}
private SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth())
.build();
}
private List<SecurityReference> defaultAuth() {
final AuthorizationScope[] authorizationScopes = new AuthorizationScope[3];
authorizationScopes[0] = new AuthorizationScope("read", "read all");
authorizationScopes[1] = new AuthorizationScope("trust", "trust all");
authorizationScopes[2] = new AuthorizationScope("write", "write all");
return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes));
}
// @Bean
// public SecurityConfiguration security() {
// return new SecurityConfiguration
// ("client", "secret", "", "", "Bearer access token", ApiKeyVehicle.HEADER, HttpHeaders.AUTHORIZATION,"");
// }
@Bean
SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.clientId("client_test")
.clientSecret("secret_test")
.realm("test-app-realm")
.appName("test-app")
.scopeSeparator(",")
.additionalQueryStringParams(null)
.useBasicAuthenticationWithAccessCodeGrant(false)
.build();
}
@Bean
UiConfiguration uiConfig() {
return UiConfigurationBuilder.builder()
.deepLinking(true)
.displayOperationId(false)
.defaultModelsExpandDepth(1)
.defaultModelExpandDepth(1)
.defaultModelRendering(ModelRendering.EXAMPLE)
.displayRequestDuration(false)
.docExpansion(DocExpansion.NONE)
.filter(false)
.maxDisplayedTags(null)
.operationsSorter(OperationsSorter.ALPHA)
.showExtensions(false)
.tagsSorter(TagsSorter.ALPHA)
.validatorUrl(null)
.build();
}
}
UserController
@Api(value = "用戶接口服務", description = "用戶接口服務")
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private UserRepository userRepository;
@ApiOperation(value = "查詢通過 OAuth2.0 授權后獲取的用戶信息", notes = "通過 OAuth2.0 授權后獲取的用戶信息")
@GetMapping("/principal")
public Principal principal(Principal principal)
{
return principal;
}
@ApiOperation(value = "根據用戶名查詢用戶信息", notes = "根據用戶名查詢用戶信息")
@GetMapping("/{username}")
public BaseMsg GetUserInfoByUserName(@PathVariable String username) {
return BaseMsgResponse.success(userRepository.findOneByusername(username));
}
@ApiOperation(value = "根據ID刪除一個用戶", notes = "根據ID刪除一個用戶")
@DeleteMapping("/{id}")
public BaseMsg getInfoByName(@PathVariable Integer id) {
userRepository.deleteById(id);
return BaseMsgResponse.success();
}
}
最后訪問 http://localhost:8080/swagger-ui.html#/
配置 Resource Owner Password Credentials 模式的 Client
Test
問題:
swagger-2.9.1 /csrf is 404 問題
A:這個問題在 2.9.x 版本中有(https://github.com/springfox/springfox/issues/2603) ,暫時還沒有找到好的解決方案,回退到 2.8.0 版本。
配置 ApiKey 后 HTTP 頭 Authorization: Bearer {THE TOKEN} 不生效問題
A:2.7.x 版本沒有問題(https://github.com/springfox/springfox/issues/1812)
@Bean public SecurityScheme apiKey() { return new ApiKey(HttpHeaders.AUTHORIZATION, "apiKey", "header"); }
后面使用了 OAuth2.0 協議在 2.8.0 版本中無問題。
REFER:
https://springfox.github.io/springfox/docs/current/
https://github.com/springfox/springfox
https://github.com/rrohitramsen/spring-boot-oauth2-jwt-swagger-ui



