[Java]URL安全的Base64编码实现

2022-11-23 1406点热度 0人点赞 0条评论

前言

我们有时候需要在GET的参数中传递参数,例如是byte[]类型的内容,一般来说是转成Base64的编码格式,但是带来一个问题是:base64编码后,里面可能会出现一些字符是url里面冲突的,例如=+/这些,虽然可以URLEncode进行编码,但这还是会给程序带来一些复杂度或者不确定性。

URL编码规范

关于URL编码的详细规范,可以查看RFC 3986, 这里只对我们会涉及的信息做简要说明。

RFC 3986中有如下两个重要规定:

  • Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、- _ . ~4个特殊字符以及所有保留字符。
  • 保留字符包括:! * ' ( ) ; : @ & = + $ , / ? # [ ]

另外,还有很多字符,当它们直接放在Url中的时候,可能会引起解析程序的歧义。

这些字符被视为不安全字符,原因有很多。

  • 空格:Url在传输的过程,或者用户在排版的过程,或者文本处理程序在处理url的过程,都有可能引入无关紧要的空格,或者将那些有意义的空格给去掉;
  • 引号以及<>:引号和尖括号通常用于在普通文本中起到分隔Url的作用;
  • #:通常用于表示书签或者锚点;
  • %:百分号本身用作对不安全字符进行编码时使用的特殊字符,因此本身需要编码;
  • { } | \ ^ [ ] ` ~:某一些网关或者传输代理会篡改这些字符。

url安全的base64编码

在实际的应用中,url参数的字符串是一个base64编码的json字符串,这就可能出现不符合url编码规范的结果, 因为base64编码会出现+/=这些被url转码的特殊字符,一旦这个结果被转码了,第三方应用获取到的base64字符串和服务端 签名生成的就不一致了,因此对它编码必须是url安全的base64编码。

url安全的base64编码规范一般采用如下方式:

  • 将base64中的+号换成-
  • 将base64中的/号换成_
  • 将base64中的=号换成空字符串,即删除=

对应的,url安全的base64解码过程要反过来:

  • 将base64中的-号换成+
  • 将base64中的_号换成/
  • 在base64中末位补齐=号,使得base64的字符数量可以被4整除

java编码示例代码如下:

public static String safeUrlBase64Encode(byte[] data) {
    String encodeBase64 = new String(Base64.getEncoder().encode(data));
    String safeBase64Str = encodeBase64.replace('+', '-');
    safeBase64Str = safeBase64Str.replace('/', '_');
    safeBase64Str = safeBase64Str.replaceAll("=", "");
    return safeBase64Str;
}

java解码示例代码如下:

public static byte[] safeUrlBase64Decode(final String safeBase64Str) {
    String base64Str = safeBase64Str.replace('-', '+');
    base64Str = base64Str.replace('_', '/');
    int mod4 = base64Str.length() % 4;
    if (mod4 > 0) {
        base64Str = base64Str + "====".substring(mod4);
    }
    return Base64.getDecoder().decode(base64Str);
}

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论