关于Java中的base64:base64url

base64url in java

https://web.archive.org/web/20110422225659/https://en.wikipedia.org/wiki/Base64#URL_applications

谈论base64Url-解码

存在用于URL变体的修改的Base64,其中不使用填充\\'= \\',标准Base64的\\'\\'和\\'/ \\'字符分别替换为\\'-\\'和\\ '_ \\'

我创建了以下函数:

1
2
3
4
5
6
7
8
9
10
11
public static String base64UrlDecode(String input) {
    String result = null;
    BASE64Decoder decoder = new BASE64Decoder();
    try {
        result = decoder.decodeBuffer(input.replace('-','+').replace('/','_')).toString();
    }
    catch (IOException e) {
        System.out.println(e.getMessage());
    }
    return result;
}

它返回一组很小的字符,这些字符甚至与预期的结果都不相似。
有什么想法吗?


Java8

1
2
3
4
import java.util.Base64;


return Base64.getUrlEncoder().encodeToString(bytes);


从Java 8开始,

Base64编码是JDK的一部分。java.util.Base64.getUrlEncoder()也支持URL安全编码,并且可以通过另外使用java.util来跳过" ="填充。 Base64.Encoder.withoutPadding()方法:

1
2
3
4
5
6
7
8
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public String encode(String raw) {
    return Base64.getUrlEncoder()
            .withoutPadding()
            .encodeToString(raw.getBytes(StandardCharsets.UTF_8));
}


使用Apache Commons的Base64(可以将其配置为URL安全),我创建了以下函数:

1
2
3
4
5
6
7
8
9
import org.apache.commons.codec.binary.Base64;

public static String base64UrlDecode(String input) {
    String result = null;
    Base64 decoder = new Base64(true);
    byte[] decodedBytes = decoder.decode(input);
    result = new String(decodedBytes);
    return result;
}

构造函数Base64(true)使解码URL安全。


在Android SDK中,Base64类中有一个专用标志:Base64.URL_SAFE,像这样使用它来解码为字符串:

1
2
3
import android.util.Base64;
byte[] byteData = Base64.decode(body, Base64.URL_SAFE);
str = new String(byteData,"UTF-8");

番石榴现在内置了Base64解码。

https://google.github.io/guava/releases/17.0/api/docs/com/google/common/io/BaseEncoding.html


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static byte[] encodeUrlSafe(byte[] data) {
    byte[] encode = Base64.encode(data);
    for (int i = 0; i < encode.length; i++) {
        if (encode[i] == '+') {
            encode[i] = '-';
        } else if (encode[i] == '/') {
            encode[i] = '_';
        }
    }
    return encode;
}

public static byte[] decodeUrlSafe(byte[] data) {
    byte[] encode = Arrays.copyOf(data, data.length);
    for (int i = 0; i < encode.length; i++) {
        if (encode[i] == '-') {
            encode[i] = '+';
        } else if (encode[i] == '_') {
            encode[i] = '/';
        }
    }
    return Base64.decode(encode);
}


马上行动,看来您的replace()是倒退的;该方法用第二个字符代替第一个字符的出现,而不是相反。


@ufk的答案有效,但是在解码时实际上不需要设置urlSafe标志。

urlSafe is only applied to encode operations. Decoding seamlessly
handles both modes.

此外,还有一些静态助手可以使它更短,更明确:

1
2
3
4
5
6
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;

public static String base64UrlDecode(String input) {
  StringUtils.newStringUtf8(Base64.decodeBase64(input));
}

文档

  • newStringUtf8()
  • encodeBase64()

此类可以帮助您:

1
2
3
4
5
6
7
8
9
10
11
12
import android.util.Base64;

public class Encryptor {

    public static String encode(String input) {
        return Base64.encodeToString(input.getBytes(), Base64.URL_SAFE);
    }

    public static String decode(String encoded) {
        return new String(Base64.decode(encoded.getBytes(), Base64.URL_SAFE));
    }
}

在Java中,尝试使用Commons Codec库中的方法Base64.encodeBase64URLSafeString()进行编码。