【问题标题】:Multiple Variables into 1 in a URLURL中的多个变量为1
【发布时间】:2009-09-07 14:41:13
【问题描述】:

我希望在 URL 中传递参数列表。

$url['key1']=1;
$url['key2']=2;
$url['key3']=3;
$url['key4']=4;
$url['key5']=5;
$url['key6']=6;
$url['key7']=7;

请注意,我试图在 1 个 GET 变量中的 URL 中传递它。我知道 ?key1=1&key2=2&key3=3...etc 会更好地完成,但由于原因太复杂而无法尝试解释它们不能采用这种格式。

有什么建议可以将这个数组转换为可以作为 URL 字符串中的 1 get var 传递的东西吗?

提前致谢。

【问题讨论】:

  • 你没有指出这个数据的语义。让远程匿名用户直接操作 $url 可能存在严重的安全问题。

标签: php arrays url query-string


【解决方案1】:

您可以使用json_encode()serialize()

$myUrl = 'http://www.example.com/?myKey=' . urlencode(json_encode($url));

$myUrl = 'http://www.example.com/?myKey=' . urlencode(serialize($url));

使用json_encode 通常会给你一个更短的字符串,但非常旧的PHP 版本可能没有json_decode 函数可用于再次对其进行解码。

最后的方法是创建您自己的自定义编码...它可以像管道分隔值一样简单:key1|1|key2|2|key3|3
这将为您提供短 URL 的最佳选择,但也是最有效的。

【讨论】:

  • 我曾想过,但字符串变得很长:serialized = :7:{s:4:"key1";i:1;s:4:"key2";i:2; s:4:"key3";i:3;s:4:"key4";i:4;s:4:"key5";i:5;s:4:"key6";i:6;s: 4:"key7";i:7;} 带 url_enode: a%3A7%3A%7Bs%3A4%3A%22key1%22%3Bi%3A1%3Bs%3A4%3A%22key2%22%3Bi%3A2%3Bs% 3A4%3A%22key3%22%3Bi%3A3%3Bs%3A4%3A%22key4%22%3Bi%3A4%3Bs%3A4%3A%22key5%22%3Bi%3A5%3Bs%3A4%3A%22key6%22% 3Bi%3A6%3Bs%3A4%3A%22key7%22%3Bi%3A7%3B%7D 长度会有问题吗?
  • ~200 个字符并不是真正的问题......只是非常难看。改用 json
  • 您可以使用大约 2048 个字符,但理论上应该没有限制:stackoverflow.com/questions/417142/…
  • {"key1":1,"key2":2,"key3":3,"key4":4,"key5":5,"key6":6,"key7":7和 %7B%22key1%22%3A1%2C%22key2%22%3A2%2C%22key3%22%3A3%2C%22key4%22%3A4%2C%22key5%22%3A5%2C%22key6%22%3A6 %2C%22key7%22%3A7%7D 更好,只是尝试做一些对眼睛更容易的事情:(
  • 如果字符串太长,您可以使用 bzcompress()。更大的问题是这种方法可能存在安全问题,因为最终用户可以(然后)直接创建他们喜欢的任何类型的 PHP 对象,具有任何值。即使远端只是简单地“打印”结果,你也得到了 XSS 攻击向量。
【解决方案2】:

试试http_build_query:

$url['key1']=1;
$url['key2']=2;
$url['key3']=3;
$url['key4']=4;
$url['key5']=5;
$url['key6']=6;
$url['key7']=7;

echo http_build_query($url);
//echos key1=1&key2=2&key3=3&key...

它的作用是使用键将数组转换为查询字符串,并自动处理 url 编码。

编辑

只需阅读您的附加要求,即它应该只是一个变量。所以不要介意这个答案。 如果您的问题是正确的编码,尽管您可能想再试一次。

希望对您有所帮助。

【讨论】:

  • 你给了我一个主意:echo $newurl = http_build_query($url,"","|");这可以给我: ?key1=1|key2=2|key3=3|key4=4|key5=5|key6=6|key7=7
  • 这不是我五分钟前说的吗? :|
【解决方案3】:

建议使用serialize() 很好。如果空间是个问题,请结合使用bzcompress()serialize()

但是,考虑到尚未提出的安全问题,即最终用户(可以查看和编辑此 url)可以操纵其中的数据。您可能认为这很困难,但是野外大多数攻击 PHP 的蠕虫都在某种程度上做到了这一点。

如果让用户直接操作 任何 键或值(或将其替换为整数、对象或其他任何内容),那么您应该保护您的脚本(和您的用户)从这次攻击中。

一个简单的解决方案是简单地使用共享密钥。它可以是任何东西;只要它是唯一且真正保密的(也许您应该在安装时随机生成它)。假设您的配置文件中有这样的内容:

define('SECRET', 'unoqetbioqtnioqrntbioqt');

然后,您可以使用$k=sha1($s.SECRET) 对使用$s=serialize($m) 创建的序列化数据进行数字签名,并将url 值设为$k.$s

然后,在你 unserialize() 之前这样做:

$v=substr($input,0,40);
$s=substr($input,40);
if ($v != sha1($s.SECRET)) { die("invalid input"); }
$m=unserialize($s);

这样,你就知道$m和你序列化的原始值是一样的。

如果您愿意,可以使用以下插入式替换:

define('SECRET','buh9tnb1094tib014'); // make sure you pick something else
function secureserialize($o) {
  $s=serialize($o);
  return sha1($s.SECRET).$s;
}
function secureunserialize($i) {
  $v=substr($i,0,40);$s=substr($i,40);
  if ($v!=sha1($s.SECRET)){die("invalid input");}
  return unserialize($s);
}

【讨论】:

    【解决方案4】:

    您可以在构造 URL 时将 serialize 它们作为键值对,将生成的序列化值放入单个 $_GET 变量(例如 data=sfsdfasdf98sdfasdf),然后将 unserialize $_GET["data"] 变量。您需要使用 urlencode 来确保生成的序列化值是 URL 安全的。请务必注意最大 URL 长度 - 2083 characters in IE

    但是,除非您真的不能在 URL 中使用键值对(根据您的问题),否则key1=foo&key2=bar... 绝对是要走的路。

    【讨论】:

    • 您也可以使用 bzcompress() 来节省空间。另请注意,使用 serialize() 可能存在安全注意事项,具体取决于您对 unserialize() 数据使用的内容。
    【解决方案5】:

    如果您不介意删除键名,可以使用

    http://example.com?url[]=1&url[]=2&url[]=3

    EDIT 保留键名:

    http://example.com?values[]=1&values[]=2&values[]=3&keys[]=1&keys[]=2&keys[]=3

    然后在你的 PHP 脚本中:

    $url = array_combine($_GET['keys'], $_GET['values']);
    

    【讨论】:

    • 对不起,我需要键名:(
    【解决方案6】:

    您能否通过将数据保存为 HTML cookie 来解决您的问题?这样你就根本不需要修改 URL。

    如果您事先知道这些值,则可以在向用户发送带有目标链接的页面时从服务器端设置它们。

    如果您在用户填写表单之前不知道这些值,仍然可以使用 JavascriptL 完成当用户单击表单提交时,您可以通过进行多个 javascript 调用来设置多个 cookie,例如: document.cookie = 'key1=test; expires=2009 年 9 月 7 日星期一 23:47:11 UTC;路径=/'

    如果您尝试将此数据从一个域传递到另一个域,安全模型可能会给您带来一些麻烦。

    【讨论】:

    • 问题仍然存在:如何对数据进行编码,即使您解决了实际放置数据的位置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多