经过大家的艰苦奋战,完成了一次大版本上线,所涉及的产品、交易较多,测试方面也投入了较大精力,相关交易验证完毕后,大家高兴的散去。
果然,刚到家打开手机,还是出事了,存量未修改的部分产品风控拒绝率飙升,通过业务监控指标来看,这种拒绝率很有可能是代码导致的。
还是原来的套路,还是熟悉的配方,打开电脑连上VPN,经过交易数据分析,结合相关日志情况,清楚的发现部分数据源加密异常了。
tried to access method org.bouncycastle.math.ec.ECPoint$Fp.(Lorg/bouncycastle/math/ec/ECCure;Lorg/bouncycastle/math/ec/ECFieldElement;)V from class com.zgcbank.rds.sm.SM2
‘Fp(org.bouncycastle.math.ec.ECCure, org.bouncycastle.math.ec.ECFoieldElement)’ is not public in ‘org.bouncycastle.math.ec.ECPoint.Fp’. Cannot be accessed from outside package
根据报错信息,发现试图访问方法#Fp,发现非public类型方法,包外无法访问。
1.排查相关报错的数据接口依赖信息,发现代码中依赖了三个版本的jdk15on的包:
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15onartifactId>
<version>1.65version>
dependency>
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15onartifactId>
<version>1.59vCureersion>
dependency>
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15onartifactId>
<version>1.52version>
dependency>
排查相关依赖包:bcprov-jdk15on-1.52 ~ bcprov-jdk15on-1.65
bcprov-jdk15on-1.52
public static class Fp extends ECCurve.AbstractFp {
private static final int FP_DEFAULT_COORDS = 4;
BigInteger q;
BigInteger r;
org.bouncycastle.math.ec.ECPoint.Fp infinity;
public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
}
......
public static class Fp extends ECPoint.AbstractFp {
@Deprecated
public Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
this(var1, var2, var3, false);
}
bcprov-jdk15on-1.59
public static class Fp extends ECCurve.AbstractFp {
private static final int FP_DEFAULT_COORDS = 4;
BigInteger q;
BigInteger r;
org.bouncycastle.math.ec.ECPoint.Fp infinity;
public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
}
......
public static class Fp extends ECPoint.AbstractFp {
/** @deprecated */
public Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
this(var1, var2, var3, false);
}
bcprov-jdk15on-1.65
public static class Fp extends ECCurve.AbstractFp {
private static final int FP_DEFAULT_COORDS = 4;
BigInteger q;
BigInteger r;
org.bouncycastle.math.ec.ECPoint.Fp infinity;
/** @deprecated */
public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
}
......
public static class Fp extends ECPoint.AbstractFp {
Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
super(var1, var2, var3);
}
根据上述#Fp(ECCurve , ECFieldElement , ECFieldElement )相关信息,得出结论 bcprov-jdk15on-1.52 、 bcprov-jdk15on-1.59、 bcprov-jdk15on-1.65三个包中,前两个满足访问条件,继续分析。
分析相关依赖在项目中的影响,根据
maven
依赖调用链路分析,1.59
该版本使用相对独立,鉴于目前BUG
紧急修复的情况,确定可以先不动。
接下来就是
1.52
和1.65
两个冲突版本的分析了,由第三步源码分析得出,两个版本Class
使用方式不一致,检查代码发现各自版本皆有引用,且第三方数据加密格式不尽相同,短时间很难去完成版本统一改造升级。
鉴于此,第一思路就是尝试重新写引用较少的
1.65
版本代码,重新写了10
个类之后,发现引用的内容较多,重写的工作量较大,且影响代码整洁性。
有没有方式能兼容两套加解密的方式呢,从包构建的角度,我要改变其中一个版本(优先选择使用较少的
1.65
)的包路径,考虑采用maven-shade-plugin
实现。
maven-shade-plugin
相关依赖包导入私服,版本如下
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-shade-pluginartifactId>
<version>3.2.4version>
建立空的
maven
工程在pom
文件中完成maven-shade-plugin
相关包构建plugin
引入,并完成打包构建。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-shade-pluginartifactId>
<version>3.2.4version>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>shadegoal>
goals>
<configuration>
<relocations>
<relocation>
<pattern>org.bouncycastlepattern>
<shadedPattern>shaded.org.bouncycastleshadedPattern>
relocation>
relocations>
configuration>
execution>
executions>
plugin>
plugins>
build>
完成代码中
1.65
版本相关内容的替换,进行相关数据接口验证。
相关应用(引用了1.65
和1.52
版本jar
)的应用节点启动报错:
java.lang.SecurityException:Invalid singnature file digest for Manifest main attributes
at sun security.util.SignatureFileVerfier.processImpl(SignatureFileVerfier.java:330)
删除`第三步标题2中`红框中相关信息,重启应用,正常。
services
versions
BC1024KE.SF
BC1024KE.DSA
BC2048KE.SF
BC2048KE.DSA
在上述pom文件节点configuration中增加过滤器,重启应用,正常。
<filters>
<filter>
<artifact>*:*artifact>
<excludes>
<exclude>META-INF/*.SFexclude>
<exclude>META-INF/*.DSAexclude>
<exclude>META-INF/*.RSAexclude>
<exclude>META-INF/services/*exclude>
<exclude>META-INF/versions/*exclude>
excludes>
filter>
filters>
测试
1.52
版本相关数据接口正常,测试1.65
接口报错:
Connect to xx.xxx.xx.xx:9009 [ /xx.xxx.xx.xx] failed Connection refused :connect
排查上述问题:Connect to xx.xxx.xx.xx:9009 [ /xx.xxx.xx.xx] failed Connection refused :connect
。
经检查,发现是使用了原来的httpclient
导致的问题,每次创建新的链接即可,本文暂不扩展,待后续补充。