我的用例包括一个前端WYSIWYG编辑器。从CSHTML前端视图以HTML5 / CSS格式获取用户输入。通过POST请求在后端控制器的操作中接收输入。最后用它来制作精美的数据库资料。
听起来很容易。使用这种editor的野兽,它非常简单且可自定义。
所见即所得编辑器textarea
嵌套在form
中,以使用POST
发送编辑器的原始HTML数据
<form class="form" asp-controller="CreationController" asp-action="CreateSnowflakeBlogpost" method="post">
<button type="submit" class="btn btn-link">Submit Snowflake Blogpost</button>
<textarea name="snowflakeHtmlContent" id="joditEditor"> </textarea>
</form>
控制器的动作接收POST参数。
[HttpPost]
public async Task<IActionResult> CreateSnowflakeBlogpost(string snowflakeHtmlContent)
{
// store HTML content in DB and do fancy operations
// redirect to something else
return RedirectToAction("PreviewSnowflakeBlogpost");
}
HTML5 / CSS标记在传递POST数据时会丢失。经检查,它们已从View成功发送。 Action的参数虽然有错误的数据。
好像在这里进行消毒,剥离了我们要保留的HTML标签的POST参数。
看来这可能有解决方案。
[Request.Unvalidated]
注释。 Deprecated。[AllowHtml]
注释。不推荐使用。参见here和here。@Html.Raw(theString)
here,但用于将不安全的数据从Controller传递到View。我们的用例则相反。如何将我的原始HTML / CSS数据从View传递到Action?满足以下条件:
无标记数据丢失。
防止构成XSS风险的不安全数据。按照guidelines。
我最终使用了Custom Model Binding,它绕过了这种过分急切的清理/数据丢失的工作。结果保留了我想要的HTML标签。
但是这会带来XSS风险。为了应对不安全数据的传递,我使用了HtmlSanitizer来省略不安全的HTML / CSS标签。
向参数添加了[ModelBinder(typeof(AllowSanitizedHtmlBinder))]
注释
[HttpPost]
public async Task<IActionResult> CreateSnowflakeBlogpost([ModelBinder(typeof(AllowSanitizedHtmlBinder))] string snowflakeHtmlContent)
{
// store HTML content in DB and do fancy operations
// redirect to something else
return RedirectToAction("PreviewSnowflakeBlogpost");
}
此自定义模型活页夹就像一个中继,可以防止POST参数中的任何数据丢失。在绑定该值以防止XSS之前,这里使用了HtmlSanitizer
。
// Custom Model Binding
using Microsoft.AspNetCore.Mvc.ModelBinding;
// HTML Sanitizer
using Ganss.XSS;
public class AllowSanitizedHtmlBinder: IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// Try to fetch the value of the argument by name
var valueProviderResult =
bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName,
valueProviderResult);
var value = valueProviderResult.FirstValue;
// Check if the argument value is null or empty
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
// Sanitize HTML from harmful XSS markup
var sanitizer = new HtmlSanitizer();
var sanitizedValue = sanitizer.Sanitize(value);
bindingContext.Result = ModelBindingResult.Success(sanitizedValue);
return Task.CompletedTask;
}
}
使用上述工作解决方案,我仍然不知道为什么默认情况下会清理并删除HTML标记。即使每个人都声称不支持此功能,并且此类责任特定于应用程序。
您不再需要[AllowHtml],因为没有人拒绝ASP.NET Core 2.0中的HTML
不需要[AllowHtml]或RequestValidationEnabled,因为我们在此系统中没有请求验证
对揭开根本原因的任何神秘帮助,将不胜感激。
我的解决方案基于:
request.Unvalidated
。