用户正在向我们的React应用程序提供一个字符串,并正在向其他用户显示该字符串。我想搜索一些字符,并用一些HTML替换它们,例如,如果我要搜索“特殊”一词,我会将其转换为:My <span class="special-formatting">special</span> word in a user string以前,我是执行此替换操作,然后将其结果通过dragonallySetInnerHTML插入到DOM中。现在,这当然给了我一个问题,用户可以在应用程序中键入并输入他们喜欢的HTML / Javascript,然后将其呈现给所有人查看。我尝试将HTML字符转义到它们的实体,但是危险地SetInnerHTML似乎正确地呈现了HTML实体,而不是将其呈现为实际字符串。 (编辑:见下文,这是实际的解决方案)有什么方法可以将其消息转换为纯字符串,同时仍保留这些特殊字符的显示,还可以在字符串中插入我自己的HTML?尝试避免在将每个字符串插入DOM后运行脚本。这是有关当前流量的更多信息。所有示例都经过了优化,仅显示相关代码。使用以下功能将用户文本提交到数据库: handleSubmit(event) { event.preventDefault(); var messageText = this.state.messageValue; //bold font is missing some common characters, fake way of making the normal font look bold if (this.state.bold == true) { messageText = messageText.replace(/\'/g, "<span class='bold-apostrophe'>'</span>"); messageText = messageText.replace(/\"/g, "<span class='bold-quote'>&quot;</span>"); messageText = messageText.replace(/\?/g, "<span class='bold-question'>?</span>"); messageText = messageText.replace(/\*/g, "<span class='bold-asterisk'>*</span>"); messageText = messageText.replace(/\+/g, "<span class='bold-plus'>+</span>"); messageText = messageText.replace(/\./g, "<span class='bold-period'>.</span>"); messageText = messageText.replace(/\,/g, "<span class='bold-comma'>,</span>"); } Messages.insert({ text: messageText, createdAt: new Date(), userId: user._id, bold: this.state.bold, }); }因此,我进行了替换,没有问题,但是,此时,messageText字符串仍可能包含不需要的用户输入HTML代码。然后,带有消息列表的主应用程序尝试呈现所有用户消息: render() { return ( <div ref="messagesList"> {this.renderMessages()} </div> );} renderMessages() { return [].concat(this.props.messages).reverse().map((message) => { return <Message key={message._id} message={message} />; } });}在Message.jsx中,我要对消息字符串进行最后修改(某些更改我不想保存到消息数据库中)并将其插入要返回的元素中: export default class Message extends React.Component { render() { var processedMessageText = this.props.message.text; //another find and replace to insert images for :image_name: strings, similar to how Discord inputs its emoji processedMessageText = processedMessageText.replace(/:([\w]+):/g, function (text) { text = text.replace(/:/g, ""); if (text.indexOf("_s") !== -1) { text = text.replace(/_s/g, ""); text = "<img class='small-smiley' src='/smileys/small/" + text + ".png'>"; return text; } else { text = "<img class='smiley' src='/smileys/" + text + ".png'>"; return text; } }); return ( <div> <div className='username'>{this.props.message.username}: </div> <div className='text' dangerouslySetInnerHTML={{ __html: processedMessageText }}></div> </div> ); }}同样,如果用户在其输入字符串中包含恶意HTML,它将遍历所有这些内容并将其输出到消息列表,这确实很糟糕。我希望可以以某种方式在字符串中执行这些所需的HTML插入,同时又不将它们可能输入的HTML呈现为实际HTML。我还想展示HTML中常用的字符,例如尖括号(),因此我要避免直接剥离它们的常见HTML字符输入字符串。由于接受的答案没有太多细节,因此我将在此发布最终的操作。在添加我自己的HTML并将其呈现到HTML元素的内容中之前,我对OWASP建议的字符进行了HTML编码。我想避免使用另一个库,所以我这样做了:messageText = messageText.replace(/\&/g, "&amp;");messageText = messageText.replace(/</g, "&lt;");messageText = messageText.replace(/>/g, "&gt;");messageText = messageText.replace(/\//g, "&#x2F;");messageText = messageText.replace(/\'/g, "&#x27;");messageText = messageText.replace(/\"/g, "&quot;");这样做之后,我不再能够插入任何恶意文件,并且使用OWASP中的各种测试字符串进行了测试,没有出现问题。 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 你不能只是对用户的污染字符串进行HTML编码。 搜索/替换并插入HTML。 然后执行dangerouslySetInnerHTML()。 那应该可以安全地逃脱用户输入的任何内容,并让您插入的HTML元素保持独立,对吗? (adsbygoogle = window.adsbygoogle || []).push({});
08-07 09:05