add*_*itt 5 html javascript reactjs
用户正在向我们的React应用提供一个字符串,并正在向其他用户显示。我想搜索一些字符,并用一些HTML替换它们,例如,如果要搜索“特殊”一词,我会将其转换为:
My <span class="special-formatting">special</span> word in a user string
以前,我是执行此替换操作,然后将结果通过危险地插入到HTML中。现在,这当然给了我一个问题,用户可以在应用程序中键入并输入他们喜欢的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'>"</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,
});
}
Run Code Online (Sandbox Code Playgroud)
因此,我进行了替换,没有问题,但是在这一点上,messageText字符串仍可能包含不需要的用户输入HTML代码。
然后,带有消息列表的主应用程序尝试呈现所有用户消息:
render() {
return (
<div ref="messagesList">
{this.renderMessages()}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
renderMessages() {
return [].concat(this.props.messages).reverse().map((message) => {
return <Message
key={message._id}
message={message} />;
}
});
}
Run Code Online (Sandbox Code Playgroud)
在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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
同样,如果用户在其输入字符串中包含恶意HTML,它将遍历所有这些内容并将其输出到消息列表,这确实很糟糕。我希望能以某种方式在字符串中执行这些所需的HTML插入,同时又不将它们可能输入的HTML呈现为实际HTML。我还想展示HTML中常用的字符,例如尖括号(<>),因此我要避免直接剥离它们的常见HTML字符输入字符串。
由于接受的答案没有太多细节,因此我将在此处发布最终的操作。在添加我自己的HTML并将其呈现到HTML元素的内容中之前,我对OWASP建议的字符进行了HTML编码。我想避免使用另一个库,所以我这样做了:
messageText = messageText.replace(/\&/g, "&");
messageText = messageText.replace(/</g, "<");
messageText = messageText.replace(/>/g, ">");
messageText = messageText.replace(/\//g, "/");
messageText = messageText.replace(/\'/g, "'");
messageText = messageText.replace(/\"/g, """);
Run Code Online (Sandbox Code Playgroud)
这样做之后,我不再能够插入任何恶意文件,并且使用OWASP中的各种测试字符串进行了测试,没有出现问题。
你就不能
dangerouslySetInnerHTML().这应该可以安全地转义用户输入的任何内容并保留插入的 HTML 元素,不是吗?
| 归档时间: |
|
| 查看次数: |
229 次 |
| 最近记录: |