Php 挑战-安全而准确地逃离此文本

Php 挑战-安全而准确地逃离此文本,php,jquery,escaping,Php,Jquery,Escaping,这是我最后一个问题的后续问题,贴在那里的答案实际上不起作用。这就是挑战。您将获得以下代码(假设包含jQuery): 失败:完全按照文本字段中的方式复制字符编码。 输入:$text=“Déjávu” 输出:字段包含文字dé;jà;vu (二) 这是我对古怪角色最有希望的解决方案,除了… 失败:未对某些字符进行编码(不确定到底是哪个字符,不在乎) 输入:$text=“Déjá” 输出:字段包含/script Déjá 4) 答案中的建议 $("input").val(unes

这是我最后一个问题的后续问题,贴在那里的答案实际上不起作用。这就是挑战。您将获得以下代码(假设包含jQuery):

失败:完全按照文本字段中的方式复制字符编码。
输入:
$text=“Déjávu”

输出:字段包含文字
dé;jà;vu

(二)

这是我对古怪角色最有希望的解决方案,除了…
失败:未对某些字符进行编码(不确定到底是哪个字符,不在乎)
输入:
$text=“Déjá”

输出:字段包含
/script Déjá

4) 答案中的建议

$("input").val(unescape("<?= urlencode($text); ?>"));
$(“输入”).val(unescape(“”);
失败:空格仍然编码为+

$("input").val(unescape(<?= rawurlencode($text); ?>"));
$(“输入”).val(unescape(“);
几乎可以。以前所有的输入都成功,但多字节的东西,如汉字,仍然是编码的。
decodeURIComponent
也不喜欢多字节字符

请注意,对我来说,像
strip_tags
这样的东西不是一个选项。一切都必须允许。人们用它来编写测验,如果有人想做一个测验来测试你对HTML的知识,那就这样吧。此外,不幸的是,我不能只将
htmlentities
转义文本注入输入标记的值字段。这些标记是动态生成的,我必须完全拆除我当前的javascript代码结构才能这样做

我觉得我是索尔,请告诉我我错了多少

编辑
假设用户最初输入了
Déjáhär föfrågor漢字存储到数据库中。这将作为
Déjáhär föfrågor漢;字;

存储(您可以在phpMyAdmin中看到它)。您可以使用:

  • (可能是最简单的选择)
  • 使用
    ENT\u引号
    或者将
    htmlspecialchars
    ENT\u NOQUOTES
    组合使用,并且如果您不希望引号变成HTML实体

    • 您需要用PHP编码,用JavaScript解码

      PHP的

      echo rawurlencode("</script> Déjà");
      //result: %3C%2Fscript%3E+D%C3%A9j%C3%A0
      
      var encoded = "%3C%2Fscript%3E+D%C3%A9j%C3%A0";
      alert(decodeURIComponent(encoded));
      //result: </script> Déjà
      
      echo rawurlencode(“Déjá”);
      //结果:%3C%2Fscript%3E+D%C3%A9j%C3%A0
      
      JavaScript的

      echo rawurlencode("</script> Déjà");
      //result: %3C%2Fscript%3E+D%C3%A9j%C3%A0
      
      var encoded = "%3C%2Fscript%3E+D%C3%A9j%C3%A0";
      alert(decodeURIComponent(encoded));
      //result: </script> Déjà
      
      var encoded=“%3C%2Fscript%3E+D%C3%A9j%C3%A0”;
      警报(解码组件(编码));
      //结果:Déjá
      
      如果不是UTF-8,您的文本是什么编码?如果您不知道,您没有文本,您有一个字节序列,这很难忠实地表示。如果您知道,您可以使用扩展名执行以下操作:

      $("input").val(<?= json_encode(mb_convert_encoding($text, "UTF-8", "ISO-8859-1")); ?>);
      
      $(“输入”).val();
      
      在这里,我假设您的输入是ISO-8859-1又名Latin-1编码,这是数据库字符串的常见情况

      编辑:这是对关于关闭脚本标记的评论的回应。我制作了这个测试文件,它可以正确显示,至少在Firefox 3.6中是这样的:

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
      <head>
          <title>Test</title>
          <script src='http://code.jquery.com/jquery-1.4.2.js'></script>
      </head>
      <form name='foo'>
          <input name='bar' id='bar'/>
      </form>
      <script language="JavaScript">
          $('input').val("<\/script>");
      </script>
      </html>
      
      
      试验
      $('input').val(“”);
      
      我找到了一个“足够好”的解决方案,大家可能会感兴趣

    • utf8\u对进入数据库的字符串进行编码。
    • 二,


      这并不是绝对完美的,因为php似乎没有任何方法可以知道用户键入之间的差异漢 或者直接键入
      漢;
      。因此,如果键入后者,它将成为前者。但我怀疑是否有人会希望这样做。

      ascii字符串的安全javascript转义

      <?php
      function js_encode($string)
      {
          $cleaned = is_null($string) ? null : '';
      
          // for each letter of the string
          for ($i=0, $len = strlen($string); $i < $len; $i++)
          {
              // get ascii number
              $ord = ord($string[$i]);
              // if [0-9] or [A-Z] or [a-z]
              $cleaned .= (47 < $ord && $ord < 58 OR 64 < $ord && $ord < 91 OR 96 < $ord && $ord < 123)
                  // use existing character
                  ? $string[$i]
                  // otherwise escape it
                  : '\x'.dechex($ord);
          }
      
          return $cleaned;
      }
      

      我不明白解决方案#3有什么问题?为什么你关心某些字符没有编码,只要浏览器正确处理它们?如果前面的问题没有解决,你就不应该再发布另一个问题……因为用户会在字段中键入
      ,提交它,它会在t处吐出
      /script
      哼哼。他们会感到困惑,如果他们在没有注意到的情况下再次提交表单,这将破坏他们的输入。为什么不使用一个丰富的编辑控件而不是纯文本?请给出一个值为
      $text
      的示例,其中
      $(“输入”).val(unescape(“)
      失败。您可以使用rawurlencode而不是urlencode,这样您就不必手动替换加号了。很好,我测试了它,它似乎可以工作。简化我的答案!对不起,失败了!对于某些输入(包括多字节字符),javascript抱怨uri组件格式不正确。@Tess在编码之前将文本转换为UTF-8如何?你说的“准确”。这提供了ByTestStream的精确表示。如果您想对这个问题有更多/更好的答案,您必须提供单元测试。这是正确的答案,您需要先将其标准化为UTF8,它会很好地工作。我一直在尝试,但关闭脚本标记仍然失败。它们变成了
      ,但这仍然打破了js。此外,多字节字符仍然无法转换回来。你能解释一下“规范化为UTF-8”吗?如果我把这个答案和我的#3结合起来,它不会中断,但是脚本标记根本不会出现。如果你直接把它放在代码中,它会工作吗?这在Firefox的jQuery1.4.2测试HTML文件中适用:
      $('input').val(“”)--该代码是否没有填充框?如果按原样使用,则多字节字符显示不正确。使用我在编辑结束时提供的完整输入字符串进行尝试。
      
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
      <head>
          <title>Test</title>
          <script src='http://code.jquery.com/jquery-1.4.2.js'></script>
      </head>
      <form name='foo'>
          <input name='bar' id='bar'/>
      </form>
      <script language="JavaScript">
          $('input').val("<\/script>");
      </script>
      </html>
      
      function repl($match)
      {
          return "\u" . dechex($match[1]);
      }
      
      function esc($string)
      {
          $s = json_encode($string);
          $s = preg_replace_callback("/&#([0-9]+);/", "repl", $s);
          return $s;
      }
      
      <?php
      function js_encode($string)
      {
          $cleaned = is_null($string) ? null : '';
      
          // for each letter of the string
          for ($i=0, $len = strlen($string); $i < $len; $i++)
          {
              // get ascii number
              $ord = ord($string[$i]);
              // if [0-9] or [A-Z] or [a-z]
              $cleaned .= (47 < $ord && $ord < 58 OR 64 < $ord && $ord < 91 OR 96 < $ord && $ord < 123)
                  // use existing character
                  ? $string[$i]
                  // otherwise escape it
                  : '\x'.dechex($ord);
          }
      
          return $cleaned;
      }