场景

当微服务中集成了swagger时,gateway中的过滤器也会对其进行过滤,经常会应该一些检验规则导致无法访问。

我这是增加了服务的权限校验,导致无法访问swagger相应路径,虽然增加了免校验规则,但由于相关页面较多,这种方式显得较为笨重。

PS:filter中的忽略规则自行处理。可参考SpringCloud:Gateway网关中自定义过滤器

方法1:忽略路径

将下列路径跳过校验即可访问swagger的资源。

token:
  rules: 
    ignore: #需要过滤的路径
       - /**/swagger-ui.html
       - /**/swagger-resources/**
       - /**/swagger-resources
       - /**/v2/api-docs
       - /**/swagger-resources/configuration/ui

方法2: 聚合显示

在gateway中增加swagger,集成相应的接口

  • 引入swagger包
<!--swagger-->
         <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
  • 重写swagger获取服务源的get方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description: 获取具体服务apidocs
 * @author: lizz
 * @date: 2020/4/28 11:01
 */
@Component
public class GwSwaggerResourceProvider implements SwaggerResourcesProvider {

    /**
     * swagger2默认的url后缀
     */
    private static final String SWAGGER2URL = "/v2/api-docs";

    /**
     * 网关应用名称
     * 配置集成的服务,名称与gateway中route的Path一致,用于拼接路径访问后端服务的swagger路径
     * 如:swagger.serivces = rider,user
     */
    @Value("${swagger.serivces}")
    private List<String> swaggerServices;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routeHosts = new ArrayList<>();
        // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上
        Set<String> dealed = new HashSet<>();
        swaggerServices.forEach(instance -> {
            // 拼接url,样式为/serviceId/v2/api-info,当网关调用这个接口时,会自动通过负载均衡寻找对应的主机
            String url = "/swagger/" + instance + SWAGGER2URL;
            if (!dealed.contains(url)) {
                dealed.add(url);
                SwaggerResource swaggerResource = new SwaggerResource();
                swaggerResource.setUrl(url);
                swaggerResource.setName(instance);
                resources.add(swaggerResource);
            }
        });
        return resources;
    }
}
  • 重写swagger的数据接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.*;

import java.util.List;

/**
 * @description: swagger访问页面
 *             限制dev和test环境下访问
 * @author: lizz
 * @date: 2020/4/28 11:02
 */
@RestController
@RequestMapping("/swagger-resources")
@Profile({"dev","test"})
public class SwaggerResourceController {
    private GwSwaggerResourceProvider swaggerResourceProvider;

    @Autowired
    public SwaggerResourceController(GwSwaggerResourceProvider swaggerResourceProvider) {
        this.swaggerResourceProvider = swaggerResourceProvider;
    }

    @RequestMapping(value = "/configuration/security")
    public ResponseEntity<SecurityConfiguration> securityConfiguration() {
        return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK);
    }

    @RequestMapping(value = "/configuration/ui")
    public ResponseEntity<UiConfiguration> uiConfiguration() {
        return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK);
    }

    @RequestMapping
    public ResponseEntity<List<SwaggerResource>> swaggerResources() {
        return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK);
    }
}
  • 因为需要访问服务的api-docs接口,因此需要对该接口进行忽略,在gateway过滤规则中增加。
    token:
        ignore:  
          - /**/api-docs

     

效果

访问服务网关的swagger-ui.html页面即可,如:http://ip:port/swagger-ui.html,在select a spec选择想看的服务即可。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐