非法参数异常的解决方案:Last encoded character is a valid base 64 alphabet but not a possible value
问题
今天在开发的过程中,前端传过来的是base64的图片地址,如下所示:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzUK/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgBkAGQAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZ…1OSXJf3djzM2Nx/dekNpcD+Fvyr07+wrXPVqcPD9oepaqIaR5d9luP7jflThb3A6qw/CvUh4csz3al/wCEbtezNTsToeXrHN7/AJVZiEi4JB/KvSR4ZtT0dh+FSL4XtT/GfyppMTlFH//Z
因为图片地址过长,只展示部分图片地址。
后端接到base64的图片地址后,需要解析出改地址信息,当时考虑到使用的是commonsc-codec进行解密,但报出来如下的错误:
Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. Expected the discarded bits to be zero.
通过断点的方式,查询出报错信息的位置,如下所示。
分析问题
于是,到源码里面看报错信息的出处,原来问题出现在这里,commonsc-codec在升级之后,其内部做了一个validateCharacter校验,报出这样的错误。
/**
* Validates whether decoding the final trailing character is possible in the context
* of the set of possible base 64 values.
*
* <p>The character is valid if the lower bits within the provided mask are zero. This
* is used to test the final trailing base-64 digit is zero in the bits that will be discarded.
*
* @param emptyBitsMask The mask of the lower bits that should be empty
* @param context the context to be used
*
* @throws IllegalArgumentException if the bits being checked contain any non-zero value
*/
private static void validateCharacter(final int emptyBitsMask, final Context context) {
if ((context.ibitWorkArea & emptyBitsMask) != 0) {
throw new IllegalArgumentException(
"Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. " +
"Expected the discarded bits to be zero.");
}
}
这段代码是什么意思呢?翻译成中文:
验证在一组可能的 base 64 值的上下文中是否可以解码最后一个尾随字符。如果提供的掩码中的较低位为零,则该字符有效。这用于测试最终的尾随 base-64 数字在将被丢弃的位中是否为零。
通过翻译可以了解到该方法的作用,然后再分析这两个参数:
-
ibitWorkArea
: 位处理的基本位数 -
numBitsToDrop
: 应该为空的低位数目
可以看出当 context.ibitWorkArea & numBitsToDrop
不为0时就会抛出异常,实际上只有base64严格模式编码下,才可能会为0,松散模式不会为0
解决问题
方式一
commons-codec版本更新到1.15,最新的源码已经处理了该问题。
引入jar包
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
查看源码:
private void validateCharacter(final int emptyBitsMask, final Context context) {
if (isStrictDecoding() && (context.ibitWorkArea & emptyBitsMask) != 0) {
throw new IllegalArgumentException(
"Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " +
"Expected the discarded bits from the character to be zero.");
}
}
方式二
可以使用谷歌的guava来替换common-codec来解密base64格式的文件
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
如下代码解析代码:
byte[] imageByte = BaseEncoding.base64().decode(imageString);
结果能正常解析。
扩展备注
base64的严格模式和松散模式定义,直接引用源码了
松散模式
任何尾随位都尽可能组合成 8 位字节。其余的被丢弃。
严格模式
严格模式: 如果尾随位,解码将引发 {@link IllegalArgumentException}不是有效编码的一部分。 最后一个字符中的任何未使用的位必须为零。 不允许对整个最终字符进行不可能计数。
相关文章
- navicat异常 - 1130-host ... is not allowed to connect to this MySql server
- Java中常见的异常类型
- C#进阶系列——WebApi 异常处理解决方案
- 《java虚拟机》----java内存区域与内存溢出异常
- 安装oracle数据库提示“程序异常终止”解决方案
- HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案
- Atitit.异常处理 嵌套 冗长的解决方案
- Atitit避免出现空指针异常解决方案
- Atitit避免出现空指针异常解决方案
- Atitit. Dwr 抛出异常error解决方案
- CV之FE:基于TF框架对图像进行数据预处理—去除异常(被损坏)图像 和单通道图像代码实现
- ML之shap:基于adult人口普查收入二分类预测数据集(预测年收入是否超过50k)利用shap决策图结合LightGBM模型实现异常值检测案例之详细攻略
- Python语言学习:python语言代码调试—异常处理之详细攻略
- 一个IIS网站的异常配置的安全解决方案
- 从可变参数函数的调用引发异常崩溃一例引发的一些思考
- Java ConcurrentModificationException 异常分析与解决方案
- 使用SoC-ML检测Azure Sentinel中的威胁—— 这个SOC-ML就是一些分析异常的规则啊!!!和ML有毛关系?!难道是自己内置的异常检测算法你可以调整参数上报异常事件???
- Java如何处理异常方法?
- “SYSTEM.DATA.SQLCLIENT.SQLCONNECTION”的类型初始值设定项引发异常---解决方案
- 【异常】记一次因错误运用数据冗余,导致的数据不一致的生产事故