Fork me on GitHub

Spring Boot 集成 Swagger2 与配置 OAuth2.0 授权

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#/

image

配置 Resource Owner Password Credentials 模式的 Client

image

Test

image

问题:

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

posted @ 2018-09-03 20:45  花儿笑弯了腰  阅读(11109)  评论(2编辑  收藏  举报