问题描述
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
口径并没有被屏蔽,还是有接口信息泄露的风险。
原因分析:
首先通过查看官方文档,我们发现在需要屏蔽的资源中确实没有包含/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来屏蔽资源。
属性配置:
#禁用springfoxspringfox.documentation.enabled=false# 如果禁用springfox,则不能开启knife4j增强,否则项目启动会报错knife4j.enable=false
来源地址:https://blog.csdn.net/w1014074794/article/details/130686632