更新(2020 年 2 月):
Microsoft 的 AntiXSS 库在其 Sanitizer 类上包含一个名为 GetSafeHtmlFragment 的静态方法,这似乎是做生意的。(由@exploring.cheerily.impresses建议)
在 .NET 4.5+ 中或通过添加System.Web.Security.AntiXss
到旧版本的 .NET 中,有一种解决此问题的好方法。我们可以[AllowHtml]
和一个自定义注解属性一起使用。该方法应将字符串中的 HTML 标记列入白名单并验证请求。
这是此作业的自定义注释属性:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
public sealed class RemoveScriptAttribute : ValidationAttribute
{
public const string DefaultRegexPattern = @"\<((?=(?!\b(a|b|i|p)\b))(?=(?!\/\b(a|b|i|p)\b))).*?\>";
public string RegexPattern { get; }
public RemoveScriptAttribute(string regexPattern = null)
{
RegexPattern = regexPattern ?? DefaultRegexPattern;
}
protected override ValidationResult IsValid(object value, ValidationContext ctx)
{
var valueStr = value as string;
if (valueStr != null)
{
var newVal = Regex.Replace(valueStr, RegexPattern, "", RegexOptions.IgnoreCase, new TimeSpan(0, 0, 0, 0, 250));
if (newVal != valueStr)
{
var prop = ctx.ObjectType.GetProperty(ctx.MemberName);
prop.SetValue(ctx.ObjectInstance, newVal);
}
}
return null;
}
}
然后你应该使用 [AllowHtml] 和 [RemoveScript] 属性来装饰你想要在其中包含 HTML 的模型属性,如下所示:
public class MyModel
{
[AllowHtml, RemoveScript]
public string StringProperty { get; set; }
}
这将只允许 <a>、<b>、<i> 和 <p> html 标记获取它。所有其他标签都将被删除,但它足够聪明,可以保留标签的内部文本。例如,如果您发送:
“这是 <u>John Smith</u> 输入的<b>富文本<b>。”
你最终会得到这个:
“这是由 John Smith 输入的<b>富文本<b>。”
将更多 HTML 标签列入白名单也很容易。例如,如果您想接受 <u></u>、<br /> 和 <hr />,请更改DefaultRegexPattern
(全局影响)或将修改后的 regexPattern 传递给 的实例RemoveScriptAttribute
,如下所示:
[AllowHtml]
[RemoveScript(regexPattern: @"\<((?=(?!\b(a|b|i|p|u|br|hr)\b))(?=(?!\/\b(a|b|i|p|u)\b))).*?\>")]
public string Body { get; set; }