【问题标题】:Sanitize HTML in Javascript object when constructing dynamic HTML forms在构建动态 HTML 表单时清理 Javascript 对象中的 HTML
【发布时间】:2020-06-12 19:21:59
【问题描述】:

我正在构建一个动态 HTML 表单,并使用来自 Javascript 对象的数据预填充字段,如下所示:

function generatePersonalForm(data) {
    html= '<form id="personalForm">'
    html+='<label for="fname">First name:</label>'
    html+='<input type="text" id="firstname" name="firstname" value="'+data.billing.contact.firstname+'"><br>'
    html+='<label for="lname">Last name:</label>'
    html+='<input type="text" id="lastname" name="lastname" value="'+data.billing.contact.lastname+'"><br>'
    html+='<label for="lname">Data:</label>'
    html+='<textarea id="emailbody" name="emailbody" rows="12" cols="50" value="'+data.emailbody+'"></textarea><br>'
    html+='<input type="submit" value="Submit">'
    html+='</form>'
    return html;
}

我从 API 接收数据对象,然后创建表单并预先填写:

document.getElementById("personalData").innerHTML = generatePersonalForm(resp);

我的 Javascript 对象 data.emailbody 有时包含 HTML(这是正确且有意的!)。但是,如果它包含像&lt;a href=\"http://www.example.com\"&gt;www.example.com&lt;/a&gt; 这样的链接,则对象中的“(双引号)会破坏表单。

单引号也是如此。是否有任何选项可以在动态添加的表单值字段中显示 HTML 内容?

【问题讨论】:

  • 我认为您需要转义 &lt;s。不过我对此并不积极。此外,innertText 在这种情况下可能会更好。

标签: javascript html jquery


【解决方案1】:

任何属性值中的任何未转义的双引号都会破坏您的代码。

let myExample = 'this is an "example" with double quotes';

'<textarea value="' + myExample + '"></textarea>'

这将产生以下无效的 HTML 混乱:

<textarea value="this is an "example" with double quotes"></textarea>

为防止这种情况,您可以转义所有双引号:

let escaped = myExample.replace(/"/g, '\\"');
// 'this is an \"example\" that will break'

这将产生这个有效的 HTML:

<textarea value="this is an \"example\" with double quotes"></textarea>

更好的是,您可以从使用字符串创建 HTML 更改为直接创建 DOM 元素:

// append <label>, <input>, <br> to form
function appendInput(form, labelTxt, inputName, inputValue) {
  let label = document.createElement('label');
  form.appendChild(label);
  label.htmlFor = inputName;
  label.innerHTML = labelTxt;
  let input = document.createElement('input');
  form.appendChild(input);
  input.id = inputName;
  input.name = inputName;
  input.value = inputValue;
  let br = document.createElement('br');
  form.appendChild(br);
}

function generatePersonalForm(data) {
  const form = document.createElement('form');
  form.id = 'personalForm';
  
  appendInput(form, 'First name:', 'firstname',
    data.billing.contact.firstname);
    
  appendInput(form, 'Last name:', 'lastname',
    data.billing.contact.lastname);

  // label and textarea
  let label = document.createElement('label');
  form.appendChild(label);
  label.htmlFor = 'emailbody';
  label.innerHTML = 'Data:';
  let txtArea = document.createElement('textarea');
  form.appendChild(txtArea);
  txtArea.id = txtArea.name = 'emailbody';
  txtArea.rows = '12';
  txtArea.cols = '50';
  txtArea.value = data.emailbody;
  let br = document.createElement('br');
  form.appendChild(br);
  
  // submit input
  let submit = document.createElement('input');
  form.appendChild(submit);
  submit.type = 'submit';
  submit.value = 'Submit';
  
  return form;
}

const dummyData = {
  billing: {
    contact: {
      firstname: 'Joe',
      lastname: '"the dude" Dokes'
      }
  },
  emailbody: 'this is an "emailbody" with double-quotes'
}

window.onload = (() => {
  const formData = generatePersonalForm(dummyData);
  let result = document.getElementById('result');
  result.appendChild(formData);
})();
<div id="result">
  Result:<br>
</div>

【讨论】:

  • 非常感谢。那条信息使我前进并独立工作。它最终导致了改用 ReactJS 的决定,而 ReactJS 正是这样做的。
【解决方案2】:

您不能在textarea 中放置超链接。 Textarea 仅用于处理文本。 如果你想要一个带有活动链接的简单文本,那么你应该使用一个 div 容器作为你的文本区域。

【讨论】:

    【解决方案3】:

    要清理 HTML,您需要将字符 &lt;&gt;"'&amp; 替换为它们的 HTML 实体,就像这个函数一样:

    function sanitizeHTML(str){
      return str.replace(/[<>"'&]/g, function(match) {
        return "&#" + match.charCodeAt(0) + ";";
      });
    }
    

    然后,在您的代码中,将对data.emailbody 的调用替换为sanitizeHTML(data.emailbody),您将获得不会破坏您的代码的净化输出。

    【讨论】:

    • 这个解决方案的美妙之处在于我可以轻松地重复使用它。谢谢。我只能选择一个作为正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 2010-12-10
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多