knife4j生产环境资源屏蔽

问题描述

knife4j是目前比较主流的自动API文档生成工具,在生产环境使用的过程中,我们一般会屏蔽或者去除Swagger的文档口径,防止接口信息泄露,保证系统安全。
但是最近在开发过程中使用knife4j-spring-boot-starter 3.0.2过程中,发现根据官网说明配置后,还是有部分Swagger的文档口径无法完全屏蔽。

项目背景spring-boot-starter-parent 2.2.6.RELEASE + knife4j-spring-boot-starter 3.0.2

<dependency>
     <groupId>com.github.xiaoymin</groupId>
     <artifactId>knife4j-spring-boot-starter</artifactId>
     <version>3.0.2</version>
 </dependency>

属性配置

# knife4j的增强配置
knife4j.enable=true
# 开启生产环境屏蔽,一定要先开启knife4j增强才会生效
knife4j.production=true

访问http://localhost:8080/doc.html,资源已被屏蔽:
在这里插入图片描述
访问/v2/api-docs地址,资源已经被屏蔽:
在这里插入图片描述

访问/v3/api-docs地址,资源未屏蔽:
在这里插入图片描述

问题小结:
在使用knife4j-spring-boot-starter 3.0.2 + openApi3.0时,通过配置knife4j.enable=true和knife4j.production=true属性,虽然屏蔽了部分Swagger的文档口径,但/v3/api-docs口径并没有被屏蔽,还是有接口信息泄露的风险。


原因分析:

官方文档:knife4j访问权限控制-生产环境屏蔽资源

首先通过查看官方文档,我们发现在需要屏蔽的资源中确实没有包含/v3/api-docs口径。
在这里插入图片描述

继续通过源码分析,在Knife4jAutoConfiguration类中,knife4j.production=true控制是否实例化ProductionSecurityFilter对象:

@Bean
    @ConditionalOnMissingBean({
    
    ProductionSecurityFilter.class})
    @ConditionalOnProperty(
        name = {
    
    "knife4j.production"},
        havingValue = "true"
    )
    public ProductionSecurityFilter productionSecurityFilter(Knife4jProperties knife4jProperties) {
    
    
        boolean prod = false;
        ProductionSecurityFilter p = null;
        if (knife4jProperties == null) {
    
    
            if (this.environment != null) {
    
    
                String prodStr = this.environment.getProperty("knife4j.production");
                if (this.logger.isDebugEnabled()) {
    
    
                    this.logger.debug("swagger.production:{}", prodStr);
                }

                prod = Boolean.valueOf(prodStr);
            }

            p = new ProductionSecurityFilter(prod);
        } else {
    
    
            p = new ProductionSecurityFilter(knife4jProperties.isProduction());
        }

        return p;
    }

而ProductionSecurityFilter继承自BasicFilter:

public class BasicFilter {
    
    
    private Logger logger = LoggerFactory.getLogger(BasicFilter.class);
    protected List<Pattern> urlFilters = null;

     //需要屏蔽的资源
    public BasicFilter() {
    
    
        this.urlFilters = new ArrayList();
        this.urlFilters.add(Pattern.compile(".*?/doc\\.html.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/v2/api-docs.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/v2/api-docs-ext.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/swagger-resources.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/swagger-ui\\.html.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/swagger-resources/configuration/ui.*", 2));
        this.urlFilters.add(Pattern.compile(".*?/swagger-resources/configuration/security.*", 2));
    }

    //路径匹配
    protected boolean match(String uri) {
    
    
        boolean match = false;
        if (uri != null) {
    
    
            Iterator var3 = this.getUrlFilters().iterator();

            while(var3.hasNext()) {
    
    
                Pattern pattern = (Pattern)var3.next();
                if (pattern.matcher(uri).matches()) {
    
    
                    match = true;
                    break;
                }
            }
        }
        return match;
    }

可以发现在knife4j-spring-boot-starter 3.0.2 版本中,BasicFilter屏蔽的资源中并不包括/v3/api-docs资源口径,这也就导致knife4j.production=true属性不能屏蔽/v3/api-docs资源口径。


解决方案:

方式一:自定义ProductionSecurityFilter

上文我们已经分析出没有屏蔽/v3/api-docs资源口径的原因是ProductionSecurityFilter对象的父类BasicFilter屏蔽的资源列表中缺少/v3/api-docs资源口径,首先想到的是是否能通过自定义ProductionSecurityFilter对象来手动添加/v3/api-docs资源口径,实现资源屏蔽。

在项目的Knife4j的配置类Knife4jConfig中添加如下代码:

     @Bean
    @ConditionalOnProperty(
            name = {
    
    "knife4j.production"},
            havingValue = "true"
    )
    public ProductionSecurityFilter productionSecurityFilter(Knife4jProperties knife4jProperties) {
    
    
        boolean prod = false;
        ProductionSecurityFilter p = null;
        if (knife4jProperties == null) {
    
    
            if (this.environment != null) {
    
    
                String prodStr = this.environment.getProperty("knife4j.production");
                log.debug("swagger.production:{}", prodStr);
                prod = Boolean.valueOf(prodStr);
            }
            p = new MyProductionSecurityFilter(prod);
        } else {
    
    
            p = new MyProductionSecurityFilter(knife4jProperties.isProduction());
        }

        return p;
    }

    //自定义ProductionSecurityFilter,添加`/v3/api-docs`资源口径
    public static class MyProductionSecurityFilter extends ProductionSecurityFilter{
    
    
        public MyProductionSecurityFilter(boolean production) {
    
    
            super(production);
            super.urlFilters.add(Pattern.compile(".*?/v3/api-docs.*", 2));
        }
    }

方式二:升级knife4j版本到3.0.3

将knife4j-spring-boot-starter升级到最新的版本3.0.3

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

该版本中BasicFilter屏蔽资源列表中已经包含/v3/api-docs资源口径:
在这里插入图片描述

方式三:禁用springfox自动配置

因为knife4j底层是依赖的springfox,也可以通过禁用springfox来屏蔽资源。
在这里插入图片描述
属性配置:

#禁用springfox
springfox.documentation.enabled=false
# 如果禁用springfox,则不能开启knife4j增强,否则项目启动会报错
knife4j.enable=false

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/w1014074794/article/details/130686632