在URL中传递base64编码的字符串

Ali*_*xel 227 php string url base64 get

通过GET参数传递原始base64编码字符串是否安全?

Joe*_*ynn 264

还有其他base64规范.(详见此处的表格).但基本上你需要65个字符来编码:26小写+ 26大写+ 10位= 62.

你还需要两个['+','/']和一个填充字符'='.但是它们都不是网友友好的,所以只要为它们使用不同的字符就可以了.上图中的标准值是[' - ','_'],但只要您对它们进行解码,就可以使用其他字符,而不需要与其他字符共享.

我建议你自己写一个帮手.喜欢这些来自base64_encodephp手册页上的评论:

function base64_url_encode($input) {
 return strtr(base64_encode($input), '+/=', '._-');
}

function base64_url_decode($input) {
 return base64_decode(strtr($input, '._-', '+/='));
}
Run Code Online (Sandbox Code Playgroud)

  • 伟大的解决方案,除了逗号在URL中是不可保留的.我建议使用'〜'(代字号)或'.' (点)代替. (53认同)
  • @kralyk:我建议只使用rodrigo-silveira的答案所建议的`urlencode`.创建两个新功能以在网址长度中保存少量字符,就像进入你的房子穿过窗户而不是只是使用门. (11认同)
  • @RandalSchwartz代字号_is_网址安全.来自RFC3986:`unreserved = ALPHA/DIGIT /" - "/"." /"_"/"〜"` (10认同)
  • @MarcoDemaio,不知道如何使用它,不可能说它只是几个字符.每个编码字符的长度都是三倍,为什么"+++ ..."不是有效的base64字符串?网址具有浏览器限制,并且网址增加三倍可能会使您达到这些限制. (5认同)
  • 由于`,`应该被urlencoded为`%2C`,我建议使用`.--`而不是`-_,`就像https://en.wikipedia.org/wiki/Base64#Variants_summary_table中的唯一变体一样尾随= (3认同)

Thi*_*raj 195

不,您需要对其进行url编码,因为base64字符串可以包含"+","="和"/"字符,这些字符可能会改变数据的含义 - 看起来像子文件夹.

有效的base64字符如下.

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
Run Code Online (Sandbox Code Playgroud)

  • 我不确定我理解你在说什么 - URL编码不会改变除上面列表中最后三个字符之外的任何字符,这是为了防止它们被错误地解释,因为它们在URLS中具有其他含义.base64也是如此,原始数据可以是二进制或任何东西,但它以一种可以使用简单协议轻松传输的形式进行编码. (19认同)
  • http://en.wikipedia.org/wiki/Base64#URL_applications - 它清楚地表明转义'使字符串不必要地更长',并提到备用字符集变体. (7认同)
  • URL编码是浪费空间,特别是因为base64本身会留下许多未使用的字符. (4认同)
  • @MichałGórny 如果您使用 JSON 作为 GET 参数,Base 64 编码将(取决于您的数据)可能会减小请求字符串的大小。(在你说这是一个愚蠢的想法之前,我们在查询字符串中使用 JSON 来促进与我们的应用程序的深度链接。)对于我们的应用程序,这种方法实现了大约 30% 的减少。(公平地说,通过完全避免 Base64 而是编写我们自己的使用 URL 编码友好字符的 JSON(反)序列化程序(例如,`(['` 而不是 `{["`),可以实现更大的减少。 (4认同)
  • 首先,您也应该转义'+',因为它可能会转换为空格.其次,至少有几个字符在URL中使用是安全的,并且不用于"标准"字符集.在某些情况下,您的方法甚至可以增加传输数据的大小_三次_; 虽然用其他字符替换这些字符会在保留相同长度的同时完成.它也是非常标准的解决方案. (3认同)
  • 由于这个答案,我将我的问题诊断为正是它提到的问题。由于 URL 处理,一些基本 64 字符(+、/、=)被更改。当我对 base 64 字符串进行 URL 编码时,问题就解决了。 (2认同)
  • 我假设你的意思是减少是通过在 url 编码之前进行 base64 来实现的,这对我来说非常有意义,因为 url 编码确实效率很低。 (2认同)

rod*_*ira 72

@joeshmo或者你可以只编写base64编码的字符串来代替编写辅助函数.这将与您的辅助函数完全相同,但不需要两个额外的函数.

$str = 'Some String';

$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );
Run Code Online (Sandbox Code Playgroud)

  • 平均从64个字符中的3个字符扩展1到3个字符,因此开销为9%(2*3/64) (4认同)
  • 结果不完全一样.urlencode使用3个字符来编码无效字符,joeshmo的解决方案使用1.这不是一个很大的区别,但它仍然是一种浪费. (2认同)

小智 38

介绍性说明我倾向于发表一些澄清,因为这里的一些答案有点误导(如果不是不正确的话).

答案是否定的,您不能简单地在URL查询字符串中传递base64编码参数,因为加号会转换为$ _GET全局数组中的SPACE.换句话说,如果你发送的test.php?myVar的= stringwith +符号

//test.php
print $_GET['myVar'];
Run Code Online (Sandbox Code Playgroud)

结果将是:
stringwith sign

解决这个问题的简单方法是在urlencode()将base64字符串添加到查询字符串之前将其简单地转义为将+,=和/字符转义为%##代码.例如,urlencode("stringwith+sign")退货stringwith%2Bsign

处理操作时,PHP会在填充$ _GET全局时自动解码查询字符串.例如,如果我给test.php的?myVar的= stringwith%2Bsign

//test.php
print $_GET['myVar'];
Run Code Online (Sandbox Code Playgroud)

结果是:
stringwith+sign

希望urldecode()返回的$ _GET字符串,因为+将被转换为空格.
换句话说,如果我发出同样的test.php?myVar的= stringwith%2Bsign

//test.php
$string = urldecode($_GET['myVar']);
print $string;
Run Code Online (Sandbox Code Playgroud)

结果出乎意料:
stringwith sign

rawurldecode()输入是安全的,然而,这将是多余的,因此是不必要的.


Mic*_*rny 13

是的,不是.

在某些情况下,base64的基本字符集可能会与URL中使用的传统约定冲突.但是许多base64实现允许你更改charset以更好地匹配URL,甚至可以随附一个(如Python urlsafe_b64encode()).

您可能面临的另一个问题是URL长度的限制或更确切地说 - 缺少此类限制.由于标准没有指定任何最大长度,因此使用HTTP协议的浏览器,服务器,库和其他软件可能会定义其自身的限制.您可以看一下这篇文章:WWW常见问题解答:URL的最大长度是多少?


And*_*ndy 8

它是一个base64url编码,你可以尝试,它只是上面的joeshmo代码的扩展.

function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
Run Code Online (Sandbox Code Playgroud)

  • 这适用于使用 Java 的 `Base64.getUrlEncoder().withoutPadding().encodeToString()` 编码的数据 (2认同)

小智 5

我认为这不安全,因为例如“=”字符用于原始 base 64 中,并且还用于区分参数和 HTTP GET 中的值。