【问题标题】:Why does %26 get decoded to & when passed as a parameter to a JavaScript function from a link?当作为参数从链接传递给 JavaScript 函数时,为什么 %26 会被解码为 &?
【发布时间】:2009-10-30 15:58:25
【问题描述】:

我们在 Web 应用程序中有一个菜单,它使用 <a> 标记在主框架中加载页面。

菜单中的典型项目类似于:

<a target="mainframe" href="/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3&param3=val4">Menu Item 1</a>

我们需要在请求链接之前添加一些 JavaScript 验证,所以我将其更改为:

<a target="mainframe" href="javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3&param3=val4')">Menu Item 1</a>  

(我知道链接中的javascript:function 是不好的做法,但我们使用第 3 方库来生成菜单,所以我无法更改这部分代码)

Servlet1 期望:
参数 1='val1'
param2='servlet2?s2p1=val2%26s2p2=val3'
param3='val4'

Servlet1 然后转发到 param2 的值,因此 Servlet2 期望:
s2p1='val2'
s2p2='val3'

但是,当我在验证函数中添加 alert 以检查传入的内容时:

function validate(href) {
    alert(href);

    ...validation code...
}

它正在给予:
/servlet1?param1=val1&parma2=servlet2?s2p1=val2**&**s2p2=val3&param3=val4(注意上面函数调用中的粗体&amp;%26

%26 在被传递到 JS 函数时被转换为 &amp;,这在请求被转发到 Servlet2 之前通常不会发生。因为%26 已经更改为&amp;,所以s2p2 请求参数被servlet1 拾取而不是servlet2

基本上我的问题是,如果您执行 onClick="validate('/servlet1?param1=val1&amp;parma2=servlet2?s2p1=val2%26s2p2=val3&amp;param3=val4')"
如您所愿,它保持为%26

【问题讨论】:

  • 不应该有两个“?”在网址中
  • 第二个“?”只是 param2 的一部分,其值为 servlet2?s2p1=val2%26s2p2=val3

标签: javascript html


【解决方案1】:
<a target="mainframe" href="javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3&param3=val4')">Menu Item 1</a>

呃。您有一个 URL,嵌入在一个 URL 中,所有这些都嵌入在另一个 URL 中!对于人类的大脑来说,逃避的层次太多了。这个:

javascript:validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2%26s2p2=val3&param3=val4')

本身就是一个 URL。尽管是 javascript: 伪 URL,但您永远不应该使用它。它被解码为 JavaScript 命令:

validate('/servlet1?param1=val1&parma2=servlet2?s2p1=val2&s2p2=val3&param3=val4')

此时您已经丢失了 %26。现在,当您将其用作 URL 本身时,它将失败。

通过将脚本移出到 JavaScript 块(或外部脚本)而不是 HTML 属性来避免多重编码问题:

<a target="mainframe" class="validateme" href="/servlet1?param1=val1&amp;parma2=servlet2?s2p1=val2%26s2p2=val3&amp;param3=val4">Menu Item 1</a>

(请注意这里还需要对 & 符号进行必要的 HTML 转义。)然后从脚本执行:

// find 'validateme' links and add event handler
//
for (var i= document.links; i-->0;)
    if (document.links[i].className==='validateme')
        document.links[i].onclick= validate;

然后在您的验证函数中,如果一切正常并且您希望链接被跟踪,则只需返回 true,或 false 停止它。

【讨论】:

  • 感谢您清楚地解释它发生的原因 - 因为它被浏览器视为伪 URL,它在被点击时被解码。我不想在 URL 中使用 javascript: 但由于使用 3rd 方库来生成问题中所述的菜单,除了为库提供调用的更新链接之外,我认为我无法做到这一点功能。您的示例向我展示了一种更好的方法。谢谢。
  • 感谢您的解释,我也遇到了这个问题,但我不知道发生了什么。请注意,双 urlencoding 也有效(即 %2526)
【解决方案2】:

不,%26 在 HTML 文件第一次读入浏览器时被(正确地)解释为 &,而不是在传递给 JavaScript 函数时。如果您想要字符的文字序列“百分之二六”,那么您必须将其编码为%2526

【讨论】:

  • 我已经检查过了。如果是这种情况,那么为什么在我进行上述更改之前单击链接并检查 Servlet1 中的 param2 的值会显示 servlet2=s2p1=val2%26s2p2=val3s2p2 参数正确地传递到 Servlet2?同样,如果我将鼠标悬停在链接上,它仍会在状态栏中显示 %26。
  • 这对我帮助很大!谢谢!
【解决方案3】:

javascript: 协议仍被视为有效 URL,因此浏览器对其进行了正确编码。在您的 Javascript 中很容易对其进行解码...

alert(decodeURIComponent(href));

【讨论】:

  • 已经在 J​​avaScript 中解码,所以在函数中 decodeURIComponent(href)=href。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
相关资源
最近更新 更多