问题
关于今天做的一个功能,需要前端从cookie
中取base64
数据发送到后端,但在后端数据校验时始终不通过。经过调试比对传输数据前后的值,发现后端接收到的数据在尾部缺少了两个等号 ’=
‘ 。
base64
的核心思想:将3个字节拆分成4个6bit,然后对每个6bit的高位补2个0,构成1个字节,也即是每3个字节最终结果将变成4个字节,如果原始字符串的字节数不是3的整数倍,那么就用0来填充,以确保编码后的字符串长度是4的倍数,这时用来填充的0被编码成了’=
‘,这就是出现=的原因。
系统中有一些值使用BASE64编码后存储在COOKIE中,当编码后的字符串最后有一个或者两个等号(=)时,使用Request.getCookies().getValue()会丢失等号,再BASE64解码时产生错误.
可以看这个issue:https://issues.apache.org/bugzilla/show_bug.cgi?id=44679,里面的讨论提到
org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE system property
that was introduced in Tomcat 6.0.24. Looks like Mark has seen the light. :)
I just wanted to update this issue so everyone that needs this feature is aware
of it
大意是:Apache Tomcat服务器在处理cookie值时,默认不允许值中包含等号(=
),因为等号在HTTP header中被用作分隔符。在Tomcat 6.0.24版本中引入了一个系统属性org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE
,通过设置这个属性为true
,可以允许cookie值中包含等号。
处理方法
- 直接从Http Head里面取Cookie的值,然后自己解析,保留value中的等号(Cookie值的格式: name=value;name2=value2;name3=value3)
- Base64解码前,计算长度,补充等号后再解码,下方是一段JS代码,用于base64不满足长度时自动填充等号
const allEncryptedData = Object.values(encryptedDataCookies).map(
(data) => {
// 检查Base64字符串的长度,并在必要时添加等号
while (data.length % 4) {
data += "=";
}
return data;
}
);