使用 MarkupString 在 Blazor 中渲染原始 HTML
·
1 分钟阅读
Available in:
中文
·
English
·
Español
·
Français
·
Deutsch
·
Português
·
한국어
·
日本語
·
Русский
·
العربية
·
हिन्दी
·
Polski
·
Türkçe
·
Bahasa Indonesia
·
Nederlands
有一天,我正在构建一个组件,需要渲染一些来自 CMS 的 HTML。我将 HTML 字符串放在一个变量中,然后将其放入模板中,例如 @myHtml。当然,Blazor 转义了所有内容并将实际标签呈现为页面上的文本。不是我想要的。
问题
默认情况下,Blazor 对您在模板中呈现的任何字符串进行编码。所以如果你有:
@code {
private string content = "<strong>Hello</strong> <em>world</em>";
}
你这样做:
<div>@content</div>
您将在页面上看到文字文本 <strong>Hello</strong> <em>world</em>,而不是 Hello world。 Blazor 这样做的目的是为了防止 XSS 攻击,这是正确的默认行为。
解决方案:MarkupString
如果您确实需要渲染原始 HTML,请将字符串包装在 MarkupString 中:
<div>@((MarkupString)content)</div>
就是这样!现在 Blazor 会将 HTML 呈现为实际标记。您还可以将其分配给变量:
@code {
private string rawHtml = "<strong>Hello</strong> <em>world</em>";
private MarkupString HtmlContent => (MarkupString)rawHtml;
}
<div>@HtmlContent</div>
一个现实世界的例子
我从 API 中提取博客内容,并需要在预览组件中呈现它。内容包含各种 HTML——标题、代码块、链接、图像。大概是这样的:
@inject HttpClient Http
@if (article is not null)
{
<article>
<h1>@article.Title</h1>
<div class="content">
@((MarkupString)article.HtmlBody)
</div>
</article>
}
@code {
[Parameter]
public int ArticleId { get; set; }
private ArticleDto? article;
protected override async Task OnInitializedAsync()
{
article = await Http.GetFromJsonAsync<ArticleDto>($"api/articles/{ArticleId}");
}
}
工作完美。来自 API 的 HTML 被呈现为实际标记。
小心不受信任的内容
这很重要:MarkupString 不会**清理 HTML。它会渲染您提供的任何内容,包括 <script> 标签。因此,如果内容来自用户输入或不受信任的来源,您需要首先对其进行清理。
Blazor 中没有内置的 HTML 清理程序,但您可以使用 HtmlSanitizer 等库:
using Ganss.Xss;
@code {
private HtmlSanitizer sanitizer = new();
private MarkupString SafeHtml(string html)
{
var clean = sanitizer.Sanitize(html);
return (MarkupString)clean;
}
}
<div>@SafeHtml(untrustedContent)</div>
这会去除危险元素,例如 <script>、onclick 处理程序以及您不希望从用户提供的内容中呈现的其他内容。
何时使用它
我使用 MarkupString 来:
- CMS 内容或 markdown 已转换为 HTML 服务器端
- 富文本编辑器输出
- 电子邮件模板预览
- 来自可信来源的任何预构建 HTML
对于来自用户输入的任何内容,始终首先进行清理。安全总比后悔好。
希望你喜欢这篇文章!请随时通过任何社交媒体与我联系:@emimontesdeoca。