通过 JavaScript 进行 Base64URL 解码?

发布于 2024-10-21 03:40:15 字数 330 浏览 3 评论 0原文

所以我很困惑。我知道有很多用于 JS 的 Base64 编码器/解码器,但没有用于修改后的(以及 Facebook 喜欢的)Base64URL 变体。到目前为止,在 stackoverflow 上的搜索已经一无所获。

是的,我可以使用 PHP 或其他服务器端库来解码它,但我试图保持它的通用性,无论我使用什么平台......例如,如果我要托管一个仅 HTML 的 Facebook 应用程序在 Amazon S3/CloudFront 上,仅使用其 JS SDK 和 jQuery 来处理表单和获取数据。

也就是说,有人知道 JavaScript 的 Base64URL 特定解码器吗?

提前致谢!

So I'm stumped. I know there's lots of Base64 encoders/decoders for JS, but not for the modified (and Facebook-favored) Base64URL variation. So far searching across stackoverflow has come up dry.

Yes, I could use PHP or another server-side library to decode this, but I'm trying to keep this universal regardless of what platform I'm using... for example, if I were to host a HTML-only Facebook app on Amazon S3/CloudFront and only use their JS SDK and jQuery to take care of processing forms and getting data.

That said, does anyone know of any Base64URL-specific decoders for JavaScript?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

与风相奔跑 2024-10-28 03:40:15

解码前使用此功能:

var decode = function(input) {
        // Replace non-url compatible chars with base64 standard chars
        input = input
            .replace(/-/g, '+')
            .replace(/_/g, '/');

        // Pad out with standard base64 required padding characters
        var pad = input.length % 4;
        if(pad) {
          if(pad === 1) {
            throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
          }
          input += new Array(5-pad).join('=');
        }

        return input;
    }

使用此功能后,您可以使用任何 Base64 解码器

Use this before decoding :

var decode = function(input) {
        // Replace non-url compatible chars with base64 standard chars
        input = input
            .replace(/-/g, '+')
            .replace(/_/g, '/');

        // Pad out with standard base64 required padding characters
        var pad = input.length % 4;
        if(pad) {
          if(pad === 1) {
            throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
          }
          input += new Array(5-pad).join('=');
        }

        return input;
    }

After using this function you can use any base64 decoder

凤舞天涯 2024-10-28 03:40:15

使用 TextEncoder 接口和 btoa() 函数,并将 + 替换为 -/ 替换为 _。最后,删除在 Base64 填充期间添加的尾随 = 字符。对于解码,过程相反。

编码

function base64URLencode(str) {
  const utf8Arr = new TextEncoder().encode(str);
  const base64Encoded = btoa(utf8Arr);
  return base64Encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

解码

function base64URLdecode(str) {
  const base64Encoded = str.replace(/-/g, '+').replace(/_/g, '/');
  const padding = str.length % 4 === 0 ? '' : '='.repeat(4 - (str.length % 4));
  const base64WithPadding = base64Encoded + padding;
  return atob(base64WithPadding)
    .split('')
    .map(char => String.fromCharCode(char.charCodeAt(0)))
    .join('');
}

Using the TextEncoder interface along with the btoa() function and replace + with -, and / is replaced with _. Finally, remove trailing = characters added during base64 padding. For Decoding, the process is reversed.

Encode

function base64URLencode(str) {
  const utf8Arr = new TextEncoder().encode(str);
  const base64Encoded = btoa(utf8Arr);
  return base64Encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

Decode

function base64URLdecode(str) {
  const base64Encoded = str.replace(/-/g, '+').replace(/_/g, '/');
  const padding = str.length % 4 === 0 ? '' : '='.repeat(4 - (str.length % 4));
  const base64WithPadding = base64Encoded + padding;
  return atob(base64WithPadding)
    .split('')
    .map(char => String.fromCharCode(char.charCodeAt(0)))
    .join('');
}
话少情深 2024-10-28 03:40:15

解决方案:

var b64str = base64.encode('foo bar');

// fix padding according to the new format
b64str = b64str.padRight(b64str.length + (4 - b64str.length % 4) % 4, '=');

使用这个出色的 Base64 编码/解码: http:// /code.google.com/p/stringencoders/source/browse/trunk/javascript/base64.js

还取决于 padRight 方法:

String.prototype.padRight = function(n, pad){
    t = this;
    if(n > this.length)
        for(i = 0; i < n-this.length; i++)
            t += pad;
    return t;
}

Solution:

var b64str = base64.encode('foo bar');

// fix padding according to the new format
b64str = b64str.padRight(b64str.length + (4 - b64str.length % 4) % 4, '=');

Using this great base64 encode/decode: http://code.google.com/p/stringencoders/source/browse/trunk/javascript/base64.js

Also depends on the padRight method:

String.prototype.padRight = function(n, pad){
    t = this;
    if(n > this.length)
        for(i = 0; i < n-this.length; i++)
            t += pad;
    return t;
}
撑一把青伞 2024-10-28 03:40:15

mohamed 的回答非常有帮助,谢谢!

如果您遇到这种情况:
throw new Error("InvalidLengthError: 输入的 base64url 字符串长度不正确,无法确定填充");

...您可能正在使用它来解码 JSON Web 令牌 (JWT)。

但为此,您需要(在替换需要替换的字符之后)正确拆分 JWT 的 3 个部分(“.”字符),然后在尝试使用该答案中的代码进行解码之前填充每个部分( https://stackoverflow.com/a/51838635/1143126)。

要快速查看 JWT 内部,如果不重要,您可以使用 https://jwt.io/安全性(例如,如果仅用于本地测试)。

The answer by mohamed was really helpful, thanks!

If this happens for you:
throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");

... you may be using it to decode a JSON Web Token (JWT).

But for this, you need to (after replacing the characters that need replacing) split apart the 3 parts of the JWT properly ("." character), and then pad each before attempting to decode using the code from that answer ( https://stackoverflow.com/a/51838635/1143126 ).

For a quick look inside your JWT, you could just use https://jwt.io/ if it's not critical to security (if it's just for a local test, for example).

凌乱心跳 2024-10-28 03:40:15

我认为进行Base64/Base64URL解码最有效的方法是直接在函数中解码,而不是将Base64URL更改为Base64然后解码。我编写了一个可以直接解码 Base64 和 Base64URL 的函数,无需任何其他依赖。

const PADCHAR = '=';
const B64index = [
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0,62,63,62,62,63,52,53,54,55,56,57,58,59,60,61, 0, 0,
    0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
  15,16,17,18,19,20,21,22,23,24,25, 0, 0, 0, 0,63, 0,26,27,28,
  29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
  49,50,51];

function b64decode(s) {
  const len = s.length;
  if (len === 0) return s;
  const padding = (s.charAt(len-1) === PADCHAR);
  const pad = padding || ((len % 4) > 0);
  const L = (Math.floor((len+3)/4)-pad)*4;
  var x = [];
  for (i = 0; i < L; i += 4)
  {
    var n = B64index[s.charCodeAt(i)] << 18 | 
      B64index[s.charCodeAt(i+1)] << 12 | 
      B64index[s.charCodeAt(i+2)] << 6 | 
      B64index[s.charCodeAt(i+3)];
    x.push(String.fromCharCode(n >> 16, (n >> 8) & 0xff, n & 0xff));
  }
  if (pad)
  {
    var n = B64index[s.charCodeAt(L)] << 18 | 
      B64index[s.charCodeAt(L+1)] << 12;
    x.push(String.fromCharCode(n >> 16));
    if (len > L + 2 && ((s.charAt(L+2) != PADCHAR) || !padding))
    {
      n |= B64index[s.charCodeAt(L+2)] << 6;
      x.push(String.fromCharCode((n >> 8) & 0xff));
    }
  }
  return x.join('');
}

为了使用此函数来解码 Base64URL 字符串,我使用 JWT 令牌作为示例。首先,我分割了令牌。然后,我解码 JWT 有效负载,然后将其解析为 JSON 对象。

const elements = token.split('.');
const payload = JSON.parse(b64decode(elements[1]));

I think the most efficient way of doing Base64/Base64URL decoding is to decode directly in a function instead of changing Base64URL into Base64 and then decoding it. I wrote a function that can decode both Base64 and Base64URL directly without any other dependency.

const PADCHAR = '=';
const B64index = [
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0,62,63,62,62,63,52,53,54,55,56,57,58,59,60,61, 0, 0,
    0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
  15,16,17,18,19,20,21,22,23,24,25, 0, 0, 0, 0,63, 0,26,27,28,
  29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
  49,50,51];

function b64decode(s) {
  const len = s.length;
  if (len === 0) return s;
  const padding = (s.charAt(len-1) === PADCHAR);
  const pad = padding || ((len % 4) > 0);
  const L = (Math.floor((len+3)/4)-pad)*4;
  var x = [];
  for (i = 0; i < L; i += 4)
  {
    var n = B64index[s.charCodeAt(i)] << 18 | 
      B64index[s.charCodeAt(i+1)] << 12 | 
      B64index[s.charCodeAt(i+2)] << 6 | 
      B64index[s.charCodeAt(i+3)];
    x.push(String.fromCharCode(n >> 16, (n >> 8) & 0xff, n & 0xff));
  }
  if (pad)
  {
    var n = B64index[s.charCodeAt(L)] << 18 | 
      B64index[s.charCodeAt(L+1)] << 12;
    x.push(String.fromCharCode(n >> 16));
    if (len > L + 2 && ((s.charAt(L+2) != PADCHAR) || !padding))
    {
      n |= B64index[s.charCodeAt(L+2)] << 6;
      x.push(String.fromCharCode((n >> 8) & 0xff));
    }
  }
  return x.join('');
}

To use this function to decode the Base64URL string, I use JWT token as an example. First, I split the token. Then, I decode the JWT payload and then parse it into JSON object.

const elements = token.split('.');
const payload = JSON.parse(b64decode(elements[1]));
旧人九事 2024-10-28 03:40:15
var str = "string";
var encoded = btoa(str); // encode a string (base64)
var decoded = atob(encoded); //decode the string 
alert( ["string base64 encoded:",encoded,"\r\n", "string base64 decoded:",decoded].join('') );
var str = "string";
var encoded = btoa(str); // encode a string (base64)
var decoded = atob(encoded); //decode the string 
alert( ["string base64 encoded:",encoded,"\r\n", "string base64 decoded:",decoded].join('') );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文