4

假设www.mydomain.com?param1=example作为一个例子。

存储作为键值对列表的第二个参数的最佳方法是什么?在我使用的那一刻&param2=key|value,key|value。我使用垂直线将键与值分开,并用逗号配对,等号之后的所有内容都使用encodeURIComponent(). 这工作正常。

但是,用户可以控制该值……作为明智的人,我们都知道用户可能会做的第一件事就是将竖线或逗号作为破坏我的参数解析器的值之一。有一个更好的方法吗?我见过 PHP 用户谈论在 url 中存储关联的数组,但我正在寻找一个纯 javascript 解决方案

4

4 回答 4

6

PHP(和其他服务器端语言)支持在查询字符串中传递数组。

www.mydomain.com?param1=example&param2[key1]=value1&param2[key2]=value2

PHP 会这样解析 GET 字符串:

array(2) {
  ["param1"]=>
  string(7) "example"
  ["param2"]=>
  array(2) {
    ["key1"]=>
    string(6) "value1"
    ["key2"]=>
    string(6) "value2"
  }
}

如果您不传递键,它将成为一个数字数组:

www.mydomain.com?param1=example&param2[]=value1&param2[]=value2

将被解析为:

array(2) {
  ["param1"]=>
  string(7) "example"
  ["param2"]=>
  array(2) {
    [0]=>
    string(6) "value1"
    [1]=>
    string(6) "value2"
  }
}

更新:您还可以在 JavaScript 中解析查询字符串。

这是我制作的一个简单的 jQuery 插件:

$.parseQuery = function(str) {
    var ret = {};
    $.each(str.split("&"), function() {
        var data = this.split('='),
            name = decodeURIComponent(data.shift()),
            val = decodeURIComponent(data.join("=")).replace('+', ' '),
            nameVal = name.match(/(.*)\[(.*)\]/);

        if (nameVal === null) {
            ret[name] = val;
        }
        else {
            name = nameVal[1];
            nameVal = nameVal[2];
            if (!ret[name]) {
                ret[name] = nameVal ? {} : [];
            }
            if ($.isPlainObject(ret[name])) {
                ret[name][nameVal] = val;
            }
            else if($.isArray(ret[name])){
                ret[name].push(val);
            }
        }
    });
    return ret;
};

然后你可以这样做:$.parseQuery('param1=example&param2[]=value1&param2[]=value2');

于 2012-08-29T14:44:48.383 回答
0

一种可能的解决方案是在将用户输入中的管道和逗号发布到您的 url 之前对其进行转义。

这意味着清理用户输入值并用不会破坏您的代码或完全剥离它们的东西替换|和。,

于 2012-08-29T14:30:54.577 回答
0

为了防止随意篡改,您可以添加校验和并对您的值进行 base-64 编码,然后 encodeURIComponent() 结果字符串。(请参阅如何使用 Javascript 编码为 Base64?A JavaScript CRC32。)

当然,这不会阻止那些真正下定决心的人弄乱你的价值观,但它会减慢那些喜欢玩弄 URL 的人的速度。

于 2012-08-29T14:52:56.430 回答
-1

当我想到序列化键值对列表时,我立即想到使用查询字符串。

对于基础知识(用于显示反序列化的 JSON):

foo=bar&foo=baz&fizz=buzz&alpha&beta=

本质上是:

{
    foo: [
        'bar',
        'baz'
    ],
    fizz: 'buzz',
    alpha: null,
    beta: ''
}

但是必须转义特殊字符:

foo=bar%26baz

本质上是:

{
    foo: 'bar&baz'
}

这意味着您可以将查询字符串作为另一个查询字符串中的值传递:

foo=bar%3Dbaz%26fizz%3Dbuzz

本质上是:

{
    foo: 'bar=baz&fizz=buzz'
}

并且foo可以解析产生:

{
    bar: baz,
    fizz: buzz
}

话虽如此,编码/解码时很容易出错,一旦开始双编码和双解码,你肯定会遇到问题。如果可以,请使用单个查询字符串来包含所有必要的数据,并且不要在查询字符串中嵌入查询字符串。

于 2012-08-29T14:39:33.350 回答