document.cookie.match不一致,有时会提取错误的cookie值

时间:2015-05-07 13:31:52

标签: javascript regex cookies google-tag-manager

我有以下脚本(在Google跟踪代码管理器中使用)

function() {
  try {
    var cml = document.cookie.match("comagic_visitor.+=.+%7C%7C.+(\\d{6})\;")[1];
    if (cml !== undefined) {
    return cml;
    }   
  } catch(e) {}  
  return 'false';
}

必须获取cookie值。 cookie的名称可能会改变,但它的第一部分始终保持不变“_comagic_visitor”。

出于某种原因,当我使用代码在控制台中获取cookie值时,我得到了正确的值:

PHPSESSID=3reongfce35dl150rbdkkllto0; region=2; region2=2; _gat_UA-XXXXXX-2=1; _ym_visorc_263098=w; _ga=GA1.3.26804606X.X431002649; _comagic_visitorTH17k=cASNWQ3N9mRZT8tSmUtTGs5IG9LaD7BPHtCCiEpq_fpSnSKGMcCsEG0kPVur16gH%7C%7C124972212; _comagic_sessionTH17k=203937260

VALUE:972212

但是在Tag Manager中使用它我得到937260(你可以看到它来自“_comagic_session”(最后6位)。

不幸的是,我不擅长调试,而且我的js技巧非常糟糕,弄清楚如何解决这个问题。关于我必须解决的问题的任何想法?

1 个答案:

答案 0 :(得分:1)

  

关于我必须解决的问题的任何想法?

您需要修复用于匹配的regular expression。 document.cookie.match()中括号中的参数是正则表达式。

From MDN, document.cookie是所有Cookie的字符串,以;分隔。由于document.cookie只是String document.cookie.match(),因此只需调用String.match()String.match(regexp)使用正则表达式参数regexp找到匹配数组。

您正在使用的正则表达式是:

comagic_visitor.+=.+%7C%7C.+(\\d{6})\;

此正则表达式表示匹配必须满足以下所有条件:

  1. comagic_visitor以comagic_visitor开头
  2. .+后跟一个或多个其他字符(除了换行符和其他几个字符之外的任何字符)。 这可能很危险
  3. =后跟=
  4. .+后跟一个或多个其他字符再次,可能很危险
  5. %7C有点危险,具体取决于您使用它的位置,可能是文字%7C或可以翻译成|,这意味着“或”
  6. .+一个或多个其他字符
  7. (\\d{6})括号将此作为匹配结果提取,\d{6}正好是6位数。如果您使用\代替/regexp/
  8. ,似乎会被额外的"regexp"转义,这是不必要的
  9. \;是转发;,需要最终;
  10. 主要问题:这个正则表达式过于宽松,并且匹配得非常多。 .+greedy,实际上它尽可能匹配,并允许正则表达式匹配所需Cookie的开头,字符串中的所有其他Cookie以及其他Cookie中的数字。由于document.cookie中的各个cookie可能无法保证按任何特定顺序排列,因此贪婪匹配的行为可能不一致。当所需的cookie位于字符串的末尾时,您将获得正确的结果。在其他时候,当.+匹配太多而且在最后可能匹配的其他cookie上有6位数时,您将不会。

    备选方案#1:编写一个简短的函数来分割;上的cookie字符串,它将分成一个字符串数组,然后将每个字符串分别送入匹配并返回第一个匹配项。这可以防止正则表达式在完整的cookie字符串中形成错误匹配。

    备选方案#2:修复正则表达式以仅匹配您想要的内容。您可以使用http://refiddle.com/或控制台窗口来测试正则表达式。可能您可以将.+更改为[^;]+,将any char except newline更改为any char except ;并且可能会修复它,因为要匹配完整Cookie字符串中的多个Cookie,它必须是允许匹配;,如果我们否认那些错误匹配应该是不可能的。

    像这样:

    var cml = document.cookie.match(/comagic_visitor[^;]+(\d{6})\;/)[1];
    

    这在nodejs中适用于我。

    d = "PHPSESSID=3reongfce35dl150rbdkkllto0; region=2; region2=2; _gat_UA-XXXXXX-2=1; _ym_visorc_263098=w; _ga=GA1.3.26804606X.X431002649; _comagic_visitorTH17k=cASNWQ3N9mRZT8tSmUtTGs5IG9LaD7BPHtCCiEpq_fpSnSKGMcCsEG0kPVur16gH%7C%7C124972212; _comagic_sessionTH17k=203937260";
    r = /comagic_visitor[^;]+(\d{6})\;/
    d.match(r)[1]
    ---> '972212'