在Java中解码base64Url

52

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

该链接介绍了base64Url - 解码。


存在一种修改后的Base64变体,称为base64Url,它不使用填充符“=”,并且将标准Base64中的“+”和“/”字符分别替换为“-”和“_”。


我创建了以下函数:

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;
}

它返回了一个非常小的字符集,甚至不像预期结果。


3
不应使用sun.misc.BASE64Decoder,因为它是内部Sun/Oracle代码(不是J2SE的一部分),并且随时可能消失。Apache Commons中的类Base64应该为您提供所需的所有功能。 - Benjamin Muschko
我的问题是如何在Java中正确解码base64url字符串。谢谢,我会尝试使用Apache Commons。 - ufk
@Benjamin,哇,我没想到BASE64Decoder是Sun的类,无论是内部还是其他。我想知道他们为什么要打破自己的命名约定。+1 - Pops
@BenjaminMuschko 可能最好澄清一下,对于那些没有意识到这是您评论中的链接的人来说,它特别是在Apache Commons_Codec_中! :) - Sled
3
应该改为 replace('_','/') - Vishal John
12个回答

89

Java8+

import java.util.Base64;


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

41
如果您不喜欢尾部的'='(填充),那么可以使用:Base64.getUrlEncoder().withoutPadding().encodeToString(str.g‌​etBytes(UTF_8))。 - jnr
1
@kiedysktos,你有一个示例序列吗?在RFC 4648中的表格“URL和文件名安全”的Base64字母表不允许在getUrlEncoder()中使用/ - Boris Treukhov
1
好的,我使用了 getEncoder() 而不是 getUrlEncoder(),这是我的错误。 - kiedysktos

51

生成的字符串仍然包含等号。这不是URL安全的,对吧? - T3rm1
8
使用Base64.getUrlEncoder().withoutPadding().encodeToString(str.getBytes(UTF_8))可以将字符串str以UTF-8编码方式转换为Base64格式并去除填充字符。 - jnr

26

利用Apache Commons中的Base64,可以配置为URL安全,我创建了以下函数:

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安全格式。


1
闲聊一下,如果你可以这样做,为什么要那么冗长呢?return new String(new Base64(true).decode(input)); - Mithaldu

8
在Android SDK中,Base64类有一个专门的标志:Base64.URL_SAFE,使用如下方式解码为字符串:
import android.util.Base64;
byte[] byteData = Base64.decode(body, Base64.URL_SAFE);
str = new String(byteData, "UTF-8");


5
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);
}

警告:结尾处的=字符会被忽略! - pi.

3
< p> 一开始看起来,你的 replace() 方法是反过来的;该方法用第二个字符替换第一个字符的出现次数,而不是相反。


2

1
这个类可以帮助:
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));
    }
}

1

我知道答案已经存在了,但是如果有人想要...

import java.util.Base64; public 

class Base64BasicEncryptionExample {  

    publicstaticvoid main(String[] args) {  

       // Getting encoder  
       Base64.Encoder encoder = Base64.getUrlEncoder();  
       // Encoding URL  
       String eStr = encoder.encodeToString
                               ("http://www.javatpoint.com/javatutorial/".getBytes());  
       System.out.println("Encoded URL: "+eStr);  

       // Getting decoder  
       Base64.Decoder decoder = Base64.getUrlDecoder();  
       // Decoding URl  
       String dStr = new String(decoder.decode(eStr));  
       System.out.println("Decoded URL: "+dStr);  
    }  
}  

参考链接:https://www.javatpoint.com/java-base64-encode-decode


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接