【问题标题】:How do I escape a string inside JavaScript code inside an onClick handler?如何在 onClick 处理程序内的 JavaScript 代码中转义字符串?
【发布时间】:2010-09-10 23:40:56
【问题描述】:

也许我只是想得太难了,但是我在弄清楚链接的 onClick 处理程序中的某些 JavaScript 代码中的字符串使用什么转义时遇到了问题。示例:

<a href="#" onclick="SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;">Select</a>

&lt;%itemid%&gt;&lt;%itemname%&gt; 是发生模板替换的地方。我的问题是项目名称可以包含任何字符,包括单引号和双引号。目前,如果它包含单引号,则会破坏 JavaScript 代码。

我的第一个想法是使用模板语言的函数来 JavaScript 转义项目名称,这只是转义引号。这不会解决包含双引号的字符串会破坏链接的 HTML 的情况。这个问题一般是怎么解决的?我是否需要对整个 onClick 处理程序进行 HTML 转义?

如果是这样,那看起来真的很奇怪,因为模板语言的转义函数也会将括号、引号和分号 HTML 化...

正在为搜索结果页面中的每个结果生成此链接,因此无法在 JavaScript 标记内创建单独的方法,因为我需要为每个结果生成一个。

另外,我正在使用我工作的公司自行开发的模板引擎,因此特定于工具包的解决方案对我没有用处。

【问题讨论】:

    标签: javascript html string escaping


    【解决方案1】:

    在 JavaScript 中,您可以将单引号编码为“\x27”,将双引号编码为“\x22”。因此,使用此方法,您可以在 JavaScript 字符串文字的(双引号或单引号)内使用 \x27 \x22 不受惩罚,而不必担心任何嵌入的引号会“中断”字符串。

    \xXX 适用于 Unicode,因此有了这些知识,您可以为通常白名单之外的所有字符创建强大的 JSEncode 函数。

    例如,

    <a href="#" onclick="SelectSurveyItem('<% JSEncode(itemid) %>', '<% JSEncode(itemname) %>'); return false;">Select</a>
    

    【讨论】:

    • 你保存了我的实际日子和未来的一些日子
    【解决方案2】:

    根据服务器端语言,您可以使用以下其中一种:

    .NET 4.0

    string result = System.Web.HttpUtility.JavaScriptStringEncode("jsString")
    

    Java

    import org.apache.commons.lang.StringEscapeUtils;
    ...
    
    String result = StringEscapeUtils.escapeJavaScript(jsString);
    

    Python

    import json
    result = json.dumps(jsString)
    

    PHP

    $result = strtr($jsString, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', 
                                     "\r" => '\\r', "\n" => '\\n' ));
    

    Ruby on Rails

    <%= escape_javascript(jsString) %>
    

    【讨论】:

    • 对于 .NET,您的答案似乎是唯一的方法。 btn.OnClientClick = "return confirm('Are you sure?')"; 是有效的,但是在其中放一个单引号的唯一方法(例如"return confirm('You're sure, right?');" 是对其进行编码......反斜杠和&amp;apos; 都不起作用。
    【解决方案3】:

    使用隐藏跨度,每个参数&lt;%itemid%&gt;&lt;%itemname%&gt; 各一个,并将它们的值写入其中。

    例如,&lt;%itemid%&gt; 的跨度看起来像 &lt;span id='itemid' style='display:none'&gt;&lt;%itemid%&gt;&lt;/span&gt;,并且在 javascript 函数 SelectSurveyItem 中从这些跨度的innerHTML 中选择参数。

    【讨论】:

    • 这确实是最好的答案。如果您将值放在 中,然后使用 jQuery $('#itemid').val() 获取它们,则不需要特殊治疗。
    【解决方案4】:

    如果要进入 HTML 属性,您需要同时对其进行 HTML 编码(至少:&amp;gt;&amp;gt; &lt;&amp;lt"&amp;quot;), and 转义单引号(带有反斜杠),这样它们就不会干扰您的 javascript 引用。

    最好的方法是使用您的模板系统(如果需要,可以扩展它),但您可以简单地创建几个转义/编码函数并将它们包装在其中的任何数据周围。

    是的,对 HTML 属性的全部内容进行 HTML 转义是完全有效的(甚至是正确的),即使它们包含 javascript。

    【讨论】:

      【解决方案5】:

      尽量避免在 HTML 中使用字符串文字,并使用 JavaScript 绑定 JavaScript 事件。

      此外,除非您真的知道自己在做什么,否则请避免使用“href=#”。它破坏了强迫性中间点击器(标签打开器)的许多可用性。

      <a id="tehbutton" href="somewhereToGoWithoutWorkingJavascript.com">Select</a>
      

      我选择的 JavaScript 库恰好是 jQuery:

      <script type="text/javascript">//<!-- <![CDATA[
      jQuery(function($){
         $("#tehbutton").click(function(){
              SelectSurveyItem('<%itemid%>', '<%itemname%>');
              return false;
         });
      });
      //]]>--></script>
      

      如果您碰巧要呈现这样的链接列表,您可能需要这样做:

      <a id="link_1" href="foo">Bar</a>
      <a id="link_2" href="foo2">Baz</a>
      
      <script type="text/javascript">
         jQuery(function($){
              var l = [[1,'Bar'],[2,'Baz']];
              $(l).each(function(k,v){
                 $("#link_" + v[0] ).click(function(){
                      SelectSurveyItem(v[0],v[1]);
                      return false;
                 });
              });
         });
       </script>
      

      【讨论】:

        【解决方案6】:

        另一个有趣的解决方案可能是这样做:

        <a href="#" itemid="<%itemid%>" itemname="<%itemname%>" onclick="SelectSurveyItem(this.itemid, this.itemname); return false;">Select</a>
        

        然后您可以对这两个变量使用标准的 HTML 编码,而不必担心 javascript 引用的额外复杂性。

        是的,这确实创建了严格无效的 HTML。但是,它一种有效的技术,并且所有现代浏览器都支持它。

        如果是我的,我可能会采用我的第一个建议,并确保值是 HTML 编码的并且有单引号转义。

        【讨论】:

        • 我个人认为这种技术是一种将数据与节点相关联的不好方法。 noteslog.com/metaobjects 是一种稍微先进的技术,但它会为您提供有效的页面并产生相同的数据。
        • 我完全同意这是一个有点肮脏的解决方案,但它肯定可以使一些棘手的事情变得容易得多。不过,这绝对是一个利基修复;)“元对象”技术是一种有趣的技术,虽然它本身有点 hacky,但我可以看到它会有什么用处。
        【解决方案7】:

        部分声明单独的函数并在 onClick 方法中调用这些函数。如果你有很多,你可以使用一个命名方案来给它们编号,或者在你的 onClicks 中传递一个整数,并在函数中有一个大的胖 switch 语句。

        【讨论】:

          【解决方案8】:

          任何值得称道的优秀模板引擎都将具有“转义引号”功能。我们的(也是本土的,我工作的地方)也有一个功能来为 javascript 转义引号。在这两种情况下,模板变量都只是附加了 _esc 或 _js_esc,这取决于你想要的。您永远不应该将用户生成的内容输出到尚未转义的浏览器,恕我直言。

          【讨论】:

            【解决方案9】:

            我也遇到过这个问题。我编写了一个脚本,将单引号转换为不会破坏 HTML 的转义双引号。

            function noQuote(text)
            {
                var newtext = "";
                for (var i = 0; i < text.length; i++) {
                    if (text[i] == "'") {
                        newtext += "\"";
                    }
                    else {
                        newtext += text[i];
                    }
                }
                return newtext;
            }
            

            【讨论】:

              【解决方案10】:

              使用包含 JavaScript 编码的 Microsoft Anti-XSS library

              【讨论】:

                【解决方案11】:

                首先,如果按这种方式设置 onclick 处理程序会更简单:

                <a id="someLinkId"href="#">Select</a>
                <script type="text/javascript">
                  document.getElementById("someLinkId").onClick = 
                   function() {
                      SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;
                    };
                
                </script>
                

                那么需要为 JavaScript 转义 itemid 和 itemname(即 " 变为 \" 等)。

                如果您在服务器端使用 Java,您可以查看来自 jakarta 的 common-lang 的 StringEscapeUtils 类。否则,编写自己的 'escapeJavascript' 方法应该不会花费太长时间。

                【讨论】:

                  【解决方案12】:

                  这里的答案是您无法使用 JavaScript 转义引号并且您需要从转义字符串开始。

                  因此。 JavaScript 无法处理字符串 'Marge 对 Peter 说“我认为那是”',您需要在将数据提供给脚本之前对其进行清理吗?

                  【讨论】:

                    【解决方案13】:

                    我遇到了同样的问题,但我以一种棘手的方式解决了它。首先制作全局变量v1、v2和v3。并在 onclick 中发送指标 1、2 或 3,并在函数中检查 1、2、3 以放置 v1、v2 和 v3 之类的:

                    onclick="myfun(1)"
                    onclick="myfun(2)"
                    onclick="myfun(3)"
                    
                    function myfun(var)
                    {
                        if (var ==1)
                            alert(v1);
                    
                        if (var ==2)
                            alert(v2);
                    
                        if (var ==3)
                            alert(v3);
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2013-03-31
                      • 2011-01-20
                      • 1970-01-01
                      • 2011-04-30
                      • 2010-10-05
                      相关资源
                      最近更新 更多