项目框架升级:Spring Boot 升级到2.6.6, Spring Framework升级到5.3.18
接到安全漏洞扫描的通知:Spring Boot 集成环境信息泄露漏洞【POC】
处置建议:Spring 官方已发布漏洞修复版本,请用户及时更新至最新版本。
原来SpringBoot框架版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
升级后首先是SpringCloud出了问题:
根据github和官网Spring Cloud版本,可知SpringCloud的兼容版本应该为2021.0.x:
对应slueth和zipkin等插件可以根据版本指定
问题2.读取yml文件报错Application run failed java.lang.ArrayIndexOutOfBoundsException: -1
这里有个yml文件是一些消息配置等,但是读取失败,报错如下:
java.lang.ArrayIndexOutOfBoundsException: -1
at org.yaml.snakeyaml.reader.StreamReader.peek(StreamReader.java:136)
at org.yaml.snakeyaml.scanner.ScannerImpl.scanToNextToken(ScannerImpl.java:1222)
at org.yaml.snakeyaml.scanner.ScannerImpl.fetchMoreTokens(ScannerImpl.java:308)
at org.yaml.snakeyaml.scanner.ScannerImpl.checkToken(ScannerImpl.java:248)
at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:634)
at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:165)
at org.yaml.snakeyaml.comments.CommentEventsCollector$1.peek(CommentEventsCollector.java:59)
at org.yaml.snakeyaml.comments.CommentEventsCollector$1.peek(CommentEventsCollector.java:45)
at org.yaml.snakeyaml.comments.CommentEventsCollector.collectEvents(CommentEventsCollector.java:140)
at org.yaml.snakeyaml.comments.CommentEventsCollector.collectEvents(CommentEventsCollector.java:119)
at org.yaml.snakeyaml.composer.Composer.composeScalarNode(Composer.java:214)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:184)
at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:314)
at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:305)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:286)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:188)
at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:314)
at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:305)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:286)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:188)
at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:314)
at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:305)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:286)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:188)
at org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:115)
at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:135)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.getData(OriginTrackedYamlLoader.java:99)
at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:514)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:198)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:166)
at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:84)
at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
at org.springframework.boot.context.config.StandardConfigDataLoader.load(StandardConfigDataLoader.java:54)
at org.springframework.boot.context.config.StandardConfigDataLoader.load(StandardConfigDataLoader.java:36)
at org.springframework.boot.context.config.ConfigDataLoaders.load(ConfigDataLoaders.java:107)
at org.springframework.boot.context.config.ConfigDataImporter.load(ConfigDataImporter.java:128)
at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:86)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
at org.springframework.boot.context.config.ConfigDataEnvironment.processWithProfiles(ConfigDataEnvironment.java:311)
at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:232)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:296)
at com.ruoyi.RuoYiApplication.main(RuoYiApplication.java:20)
根据【RuoYi-Vue-Plus】问题笔记 01 - 启动报错:Application run failed java.lang.ArrayIndexOutOfBoundsException: -1
得出,是因为yml解析器升级了,因为含有特殊符号,所以报错了
特殊符号用双引号标记成字符串。
问题三:springboot pagehelper插件启动报错 [com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration]![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f5853f1ad690216513f23e5b1f83348b.png)
根据springboot pagehelper插件启动报错 [com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration]可得原因如下:,使用的springboot版本为2.6.6,与pagehelper版本不兼容,需使用1.4.1及以上版本
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
问题3 Swagger报错
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.18.jar:5.3.18]
at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_212]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) [spring-boot-2.6.6.jar:2.6.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.6.6.jar:2.6.6]
at com.fii.gxback.auth.gxAuthApplication.main(gxAuthApplication.java:19) [classes/:na]
Caused by: java.lang.NullPointerException: null
at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:112) ~[springfox-spi-2.9.2.jar:null]
at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:109) ~[springfox-spi-2.9.2.jar:null]
at com.google.common.collect.ComparatorOrdering.compare(ComparatorOrdering.java:37) ~[guava-21.0.jar:na]
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:1.8.0_212]
at java.util.TimSort.sort(TimSort.java:234) ~[na:1.8.0_212]
at java.util.Arrays.sort(Arrays.java:1438) ~[na:1.8.0_212]
at com.google.common.collect.Ordering.sortedCopy(Ordering.java:854) ~[guava-21.0.jar:na]
at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:57) ~[springfox-spring-web-2.9.2.jar:null]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:138) ~[springfox-spring-web-2.9.2.jar:null]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:135) ~[springfox-spring-web-2.9.2.jar:null]
at com.google.common.collect.Iterators$7.transform(Iterators.java:750) ~[guava-21.0.jar:na]
at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47) ~[guava-21.0.jar:na]
at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47) ~[guava-21.0.jar:na]
at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:52) ~[guava-21.0.jar:na]
at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50) ~[guava-21.0.jar:na]
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:267) ~[guava-21.0.jar:na]
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:229) ~[guava-21.0.jar:na]
at com.google.common.collect.FluentIterable.toList(FluentIterable.java:609) ~[guava-21.0.jar:na]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.defaultContextBuilder(DocumentationPluginsBootstrapper.java:111) ~[springfox-spring-web-2.9.2.jar:null]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.buildContext(DocumentationPluginsBootstrapper.java:96) ~[springfox-spring-web-2.9.2.jar:null]
at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167) ~[springfox-spring-web-2.9.2.jar:null]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.18.jar:5.3.18]
... 14 common frames omitted
根据解决方案之‘Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPoi可知是因为升级框架导致的swagger兼容性问题。解决办法:升级swagger版本。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
第三步:
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket buildDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()) // .apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(""))// 需要生成文档的包的位置
.paths(PathSelectors.any())
.build();
}
//api的描述信息构建
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("日本电气")
.description("黑客管理系统")
.version("1.0.0")
.build();
}
/**
* 增加如下配置可解决Spring Boot 6.x 与Swagger 3.0.0 不兼容问题
**/
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
}
参考文献:
Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is java.lang.NullPointerEx
解决方案之‘Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPoi
问题四:Zuul报错
报错1:
java.lang.NoSuchMethodError: com.netflix.servo.monitor.Monitors.isObjectRegistered(Ljava/lang/String;Ljava/lang/Object;)Z
解决办法:
因为spring cloud 2020以上版本已经去除了除eureka以外的netflix套件,所以使用zuul需要导包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.9.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.netflix.servo</groupId>
<artifactId>servo-core</artifactId>
</exclusion>
</exclusions>
</dependency>
参考文献:spring cloud 2020.0.3 zuul bug
其他修复可能措施:
记一次Eureka启动报Failed to start bean ‘eurekaAutoServiceRegistration’ 。。。错误:更改httpcomponents两个包版本使得eureka版本一致,这个可以通过mvn dependency:tree查看依赖树进行分析
SpringCloud启动报错Failed to initialize DiscoveryClient
Error creating bean with name ‘scopedTarget.eurekaClient‘ defined in class原因:
在引入spring-cloud-starter-netflix-eureka-client和spring-boot-starter-web两个依赖的时候,会出现冲突。由于代码里面,我用了Spring MVC的Rest方式,而没有用spring-cloud-starter-netflix-eureka-client本身包含Jesery Rest方式。导致出现下面的BUG。
解决办法:
在eureka依赖里面排除Jersey,用SpringMVC Rest方式
Spring Cloud 异常系列 - 集成 Eureka 启动报错
添加依赖:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
</dependency>
问题五SpringBoot2.6.*禁用循环依赖问题:
spring:
main:
allow-circular-references: true
问题六:swagger404
参考解决 SpringBoot Swagger3.0 默认路径404的问题:
去掉以下注解:
@EnableSwagger2
去掉以下依赖:
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
依赖替换为:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
swagger地址为:
http://localhost:8080/swagger-ui/index.html
即可访问
问题七:Springboot :跨域报错 When allowCredentials is true, allowedOrigins cannot contain the special value “*“
原因主要是高版本springboot内置的有跨域设置,你再次配置全局跨域,会导致冲突,所以会报错
如果不想降低版本的话的,可以直接使用allowedOriginPatterns代替allowedOrigins
参考文献:Springboot :跨域报错 When allowCredentials is true, allowedOrigins cannot contain the special value “*“
问题八 swagger配置全局header
@Bean
public Docket createRestApi() {
//返回文档摘要信息
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
//.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
//.globalRequestParameters(getGlobalRequestParameters());
//.globalResponses(HttpMethod.POST, getGlobalResonseMessage());
}
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> securitySchemes = new ArrayList<>();
securitySchemes.add(new ApiKey("Authorization", "Authorization", "header"));
return securitySchemes;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$")).build());
return securityContexts;
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}