我可以将文本 属性 定义为富文本吗?
Can I define a text property as rich text?
VS 2013,VB,EF6
我正在创建一个将用户输入保存在其属性之一中的对象。我希望将用户输入存储为富文本。使存储的文本成为富文本格式涉及什么?所以,
Public Property Text as <what?>
富文本以富文本格式存储。
可在此处找到富文本格式规范:
http://www.microsoft.com/en-us/download/details.aspx?id=10725
这只是一个普通的字符串。您可以使用 SaveFile
函数从 RichTextBox 中提取字符串:
Private Function GetRTF(ByRef Box As RichTextBox) As String
Using ms As New IO.MemoryStream
Box.SaveFile(ms, RichTextBoxStreamType.RichText)
Return System.Text.Encoding.ASCII.GetString(ms.ToArray)
End Using
End Function
您可以使用 RichTextBox 的 LoadFile
方法将 Rich Text 格式的文本加载到 RichTextBox 中。文本需要采用正确的格式:
Dim rtf As String = "{\rtf1 {\colortbl;\red0\green0\blue255;\red255\green0\blue0;}Guten Tag!\line{\i Dies} ist ein\line formatierter {\b Text}.\line Das {\cf1 Ende}.}"
Using ms As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(rtf))
RichTextBox1.LoadFile(ms, RichTextBoxStreamType.RichText)
End Using
普通控件通常不会在其文本中解释这种格式属性。
我想我会 post 对于可能以与我相同的方式提出问题的其他人,我的回答是什么。我首先说明我的问题格式不正确,因为我不明白我不是真的存储 RTF,我存储的是带有 html 标签的所见即所得文本。但我认为这个问题的措辞很有用,因为这是很多人在被别人教导之前的想法。
最终这个过程会打开一个严重的XSS向量,但首先我们至少要收集所见即所得的文本。
第一步: 使用基于脚本的编辑器捕获带有 html 标签的文本。我使用了 CKEditor which is easy to download on NuGet. It comes in 3 flavors: basic, standard and full. Another popular one seems to be TinyMCE 也可以通过 NuGet 获得。
CKEditor 必须 'wired in' 才能替换现有的输入元素。我直接把@html.editorfor换成一个
<textarea name="model.UserPost.Body" id="model_UserPost_Body" class="form-control text-box multi-line">
@Html.Raw(Model.UserPost.Body)
</textarea>
CKEditor 'wired in' 使用脚本元素替换
@Section Scripts
<script src="~/scripts/ckeditor/ckeditor.js"></script>
<script>
CKEDITOR.replace('model.UserPost.Body');
</script>
End Section
上面的脚本可以通过 _layout.vbhtml 添加到所有页面,或者仅通过 @Section Scripts 部分添加到目标页面,如上所示,这通常是推荐的,也是我所做的,但这也可能需要在标准 _Layout 的
部分添加以下内容,如下所示。
@RenderSection("Styles", False)
在视图的控制器 POST 方法中,需要以下代码来捕获 WYSIWYG 文本,否则默认过滤器会在检测到任何看起来像 html 标签的内容时引发异常。
Dim rawBody = Request.Unvalidated.Form("model.UserPost.Body")
userPost.Body = rawBody
有一些可能的问题;如果正在使用 ,则必须从方法参数列表中 元素的 Include:= 列表中删除 'body' 属性。此外,虽然与此解决方案没有直接关系,但您不能在模型中的此 属性 上使用 < Required() > 之类的数据注释,因为背景检查无法确认该条件,因此 ModelState.IsValid flag 永远不会成真。
第二步:在保存输入之前必须检查 XSS。 Microsoft 有一个 nice video explaining basic XSS 我推荐查看;只有11分钟。
Mikesdotnetting 对处理 XSS 有一个很好的解释,并在 this page 的底部显示了一个白名单算法。以下代码基于他的工作。
要创建白名单方法,HTML Agility Pack 可用于对 HTML 节点进行编目以供审查。这也很容易从 Nu Get 加载。这是我在 POST 方法中调用白名单方法的代码(是的,它可以更紧凑,但对于我们新手来说更容易阅读):
Dim tempDoc = New HtmlDocument()
tempDoc.LoadHtml(rawBody)
RemoveNodes(tempDoc.DocumentNode, allowedTags)
userPost.Body = tempDoc.DocumentNode.OuterHtml
允许的标签是您将允许的,这意味着其他一切都将被拒绝,因此列入白名单。这只是一个示例列表:
Dim allowedTags As New List(Of String)() From {"p", "em", "s", "ol", "ul", "li", "h1", "h2", "h3", "h4", "h5", "h6", "strong"}
这些是基于Mikesdotnetting页面的方法:
Private Sub RemoveNodes(ByVal node As HtmlNode, allowedTags As List(Of String))
If (node.NodeType = HtmlNodeType.Element) Then
If Not allowedTags.Contains(node.Name) Then
node.ParentNode.RemoveChild(node)
Exit Sub
End If
End If
If (node.HasChildNodes) Then
RemoveChildren(node, allowedTags)
End If
End Sub
Private Sub RemoveChildren(ByVal parent As HtmlNode, allowedTags As List(Of String))
For i = parent.ChildNodes.Count() - 1 To 0 Step -1
RemoveNodes(parent.ChildNodes(i), allowedTags)
Next
End Sub
所以基本上,(1) CKEditor 使用看起来不错的 html 标签捕获用户输入,(2) 原始输入 在控制器 POST 方法,然后 (3) 使用白名单进行清理。之后可以使用@Html.Raw()直接输出到页面,因为可以信任。
就是这样。我以前没有真正 post 编辑过这样的解决方案,所以如果我遗漏了什么,请告诉我,我会更正或添加它。
VS 2013,VB,EF6
我正在创建一个将用户输入保存在其属性之一中的对象。我希望将用户输入存储为富文本。使存储的文本成为富文本格式涉及什么?所以,
Public Property Text as <what?>
富文本以富文本格式存储。
可在此处找到富文本格式规范:
http://www.microsoft.com/en-us/download/details.aspx?id=10725
这只是一个普通的字符串。您可以使用 SaveFile
函数从 RichTextBox 中提取字符串:
Private Function GetRTF(ByRef Box As RichTextBox) As String
Using ms As New IO.MemoryStream
Box.SaveFile(ms, RichTextBoxStreamType.RichText)
Return System.Text.Encoding.ASCII.GetString(ms.ToArray)
End Using
End Function
您可以使用 RichTextBox 的 LoadFile
方法将 Rich Text 格式的文本加载到 RichTextBox 中。文本需要采用正确的格式:
Dim rtf As String = "{\rtf1 {\colortbl;\red0\green0\blue255;\red255\green0\blue0;}Guten Tag!\line{\i Dies} ist ein\line formatierter {\b Text}.\line Das {\cf1 Ende}.}"
Using ms As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(rtf))
RichTextBox1.LoadFile(ms, RichTextBoxStreamType.RichText)
End Using
普通控件通常不会在其文本中解释这种格式属性。
我想我会 post 对于可能以与我相同的方式提出问题的其他人,我的回答是什么。我首先说明我的问题格式不正确,因为我不明白我不是真的存储 RTF,我存储的是带有 html 标签的所见即所得文本。但我认为这个问题的措辞很有用,因为这是很多人在被别人教导之前的想法。
最终这个过程会打开一个严重的XSS向量,但首先我们至少要收集所见即所得的文本。
第一步: 使用基于脚本的编辑器捕获带有 html 标签的文本。我使用了 CKEditor which is easy to download on NuGet. It comes in 3 flavors: basic, standard and full. Another popular one seems to be TinyMCE 也可以通过 NuGet 获得。
CKEditor 必须 'wired in' 才能替换现有的输入元素。我直接把@html.editorfor换成一个
<textarea name="model.UserPost.Body" id="model_UserPost_Body" class="form-control text-box multi-line">
@Html.Raw(Model.UserPost.Body)
</textarea>
CKEditor 'wired in' 使用脚本元素替换
@Section Scripts
<script src="~/scripts/ckeditor/ckeditor.js"></script>
<script>
CKEDITOR.replace('model.UserPost.Body');
</script>
End Section
上面的脚本可以通过 _layout.vbhtml 添加到所有页面,或者仅通过 @Section Scripts 部分添加到目标页面,如上所示,这通常是推荐的,也是我所做的,但这也可能需要在标准 _Layout 的
部分添加以下内容,如下所示。@RenderSection("Styles", False)
在视图的控制器 POST 方法中,需要以下代码来捕获 WYSIWYG 文本,否则默认过滤器会在检测到任何看起来像 html 标签的内容时引发异常。
Dim rawBody = Request.Unvalidated.Form("model.UserPost.Body")
userPost.Body = rawBody
有一些可能的问题;如果正在使用
第二步:在保存输入之前必须检查 XSS。 Microsoft 有一个 nice video explaining basic XSS 我推荐查看;只有11分钟。
Mikesdotnetting 对处理 XSS 有一个很好的解释,并在 this page 的底部显示了一个白名单算法。以下代码基于他的工作。
要创建白名单方法,HTML Agility Pack 可用于对 HTML 节点进行编目以供审查。这也很容易从 Nu Get 加载。这是我在 POST 方法中调用白名单方法的代码(是的,它可以更紧凑,但对于我们新手来说更容易阅读):
Dim tempDoc = New HtmlDocument()
tempDoc.LoadHtml(rawBody)
RemoveNodes(tempDoc.DocumentNode, allowedTags)
userPost.Body = tempDoc.DocumentNode.OuterHtml
允许的标签是您将允许的,这意味着其他一切都将被拒绝,因此列入白名单。这只是一个示例列表:
Dim allowedTags As New List(Of String)() From {"p", "em", "s", "ol", "ul", "li", "h1", "h2", "h3", "h4", "h5", "h6", "strong"}
这些是基于Mikesdotnetting页面的方法:
Private Sub RemoveNodes(ByVal node As HtmlNode, allowedTags As List(Of String))
If (node.NodeType = HtmlNodeType.Element) Then
If Not allowedTags.Contains(node.Name) Then
node.ParentNode.RemoveChild(node)
Exit Sub
End If
End If
If (node.HasChildNodes) Then
RemoveChildren(node, allowedTags)
End If
End Sub
Private Sub RemoveChildren(ByVal parent As HtmlNode, allowedTags As List(Of String))
For i = parent.ChildNodes.Count() - 1 To 0 Step -1
RemoveNodes(parent.ChildNodes(i), allowedTags)
Next
End Sub
所以基本上,(1) CKEditor 使用看起来不错的 html 标签捕获用户输入,(2) 原始输入 在控制器 POST 方法,然后 (3) 使用白名单进行清理。之后可以使用@Html.Raw()直接输出到页面,因为可以信任。
就是这样。我以前没有真正 post 编辑过这样的解决方案,所以如果我遗漏了什么,请告诉我,我会更正或添加它。