组合框填充文本字段 - JavaScript和用户输入

时间:2013-05-05 08:32:00

标签: javascript encoding combobox populate

设置

最终我需要的是:一个组合框和一个文本字段。从组合框中选择项目将填充文本字段中的值。组合框中的项目来自用户输入。

这是我当前的代码很好用:

function fill() {
  var select = document.getElementById("select");
  var value = select.options[select.selectedIndex].value;
  var textfield = document.getElementById("textfield");
  switch (value) {
  case "1":
    textfield.value = "some user-provided text";
    break;
  case "2":
    textfield.value = "containing possibly < > & etc.";
    break;
  }
}

<select id="select" onchange="fill()">
  <option>Select something...</option>
  <option value="1">Select option 1</option>
  <option value="2">Select option 2</option>
</select>

<input type="text" id="textfield"/>

问题

如果要填充的用户提供的文本包含危险字符,我不知道该怎么办。通常我会在HTML代码中编写之前对其进行HTML编码,但现在我将其编写为JavaScript代码。

所有JavaScript都是由Java后端生成的。我无法真正创建它:

String value = getValueFromUser();
write("textfield.value = \"" + value + "\";");

因为有人会输入"; somethingBad(); //,而其他一些用户会选择此选项,执行somethingBad()

如果我对值进行HTML编码:

String value = htmlEncode(getValueFromUser());
write("textfield.value = \"" + value + "\";");

然后(除了安全问题)在组合框中选择一个值之后,文本字段将填充HTML编码的文本。

问题

如何对用户提供的值进行编码,以便:

  • 它们不能被误用于JavaScript代码注入,
  • 在填充到文本字段后它们看起来一样吗?

3 个答案:

答案 0 :(得分:2)

让我提出自己的想法。

我的Java代码生成包含来自用户的HTML编码输入的隐藏HTML元素(例如spans):

<span id="case1" class="hidden">some user-provided text</span>
<span id="case2" class="hidden">containing possibly &gt; &lt; &amp; etc.</span>

然后我的JavaScript代码将使用此处的值:

function fill() {
  var select = document.getElementById("select");
  var value = select.options[select.selectedIndex].value;
  var textfield = document.getElementById("textfield");
  switch (value) {
  case "1":
    textfield.value = document.getElementById("case1").innerHTML;
    break;
  case "2":
    textfield.value = document.getElementById("case2").innerHTML;
    break;
  }
}

这样我就不用担心编码用户输入在JavaScript代码中是安全的 - 它永远不会在JS代码中!它只是在HTML内部,众所周知如何进行HTML编码以确保安全。

明显的缺点是生成隐藏的HTML元素,但这似乎是一种可接受的妥协......

答案 1 :(得分:1)

存储您的值转义,然后:

String value = getEscapedValueFromUser();
write("textfield.value = unescape(\"" + value + "\");");

这将从您存储的字符串中删除括号,引号和“=”,以防止任何恶意代码。

在以下评论之后编辑:

当您验证输入并将其完全转义存储时,您最好的选择是在js中转义它()。然后你只需要将unescape()添加到“...”之外的write()行,如上面的代码所示。

这编码了大多数特殊的字符[只是google'js escape()'以供参考]你肯定无法摆脱“......”,如果有线就没有进入下一行休息,没有需要包含在恶意代码中的字符,字符串总是最终作为输入,因为escape / unescape是互补的,你不会忘记任何事情,并且不会意外地将真正的'\ n'编码为[enter]目标字串。

如果您不想这样做,因为您可能已经在数据库中收集了大量未转义的值,或者在其他地方使用它们并且无法更改数据库以保存额外的字段,则应复制转义函数在java中你认为你需要它[在进一步认为是安全的之后你应该编码所有控制字符和"'()%=;,或者只是复制整个函数,不会太难]。

答案 2 :(得分:0)

我通常使用以下函数返回一个字符串,以显示任何类型的文本:

function RemoveEntities (TextToReplace) 
{
    var ReplacedText='';
    var CurrentChar='';
    if (typeof TextToReplace=='number') {TextToReplace=TextToReplace.toString();}
    for (i=0;i<TextToReplace.length;i++)

    {
        CurrentChar=TextToReplace.substring(i,i+1);
        if (CurrentChar=="&") {ReplacedText=ReplacedText+"&amp;";} 
        else if (CurrentChar=="<") {ReplacedText=ReplacedText+"&lt;";} 
        else if (CurrentChar==">") {ReplacedText=ReplacedText+"&gt;";} 
        else if (CurrentChar==" ") {ReplacedText=ReplacedText+"&nbsp;";} 
        else if (CurrentChar=="'") {ReplacedText=ReplacedText+"&apos;";} 
        else if (CurrentChar=='"') {ReplacedText=ReplacedText+"&quot;";} 
        else if (escape(CurrentChar)=='%0A' || escape(CurrentChar)=='%0C') {ReplacedText=ReplacedText+"<br/>";}
        else {ReplacedText=ReplacedText+CurrentChar;}
    }
return ReplacedText;
}

这应该适用于短文本输入。也可以缩短+ =或全局替换语句,但我还没有优化它(不是瓶颈)。