将HTML字符串传递给我的控制器操作方法

时间:2019-01-23 23:45:50

标签: ajax asp.net-mvc html-encode

我正在使用RTF编辑器来键入格式化的文本,如下所示:

enter image description here

我可以获取HTML格式的文本,如下所示:

<p>This is my rich HTML Text</p>

现在,我想将此HTML格式的文本传递给我的控制器,我的控制器会将这些文本放入电子邮件中,然后将其发送给收件人。

问题是HTML字符串被认为是不安全的,因此,为了将其传递给我的控制器,我需要向Action方法中添加[ValidateInput(false)]属性,如下所示:

    [ValidateInput(false)] // <-- not able to hit the action method without this
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<JsonResult> Contact(string message)
    {
        if (!HttpContext.User.Identity.IsAuthenticated)
        {
            return Json(new { Authorize = "false" });
        }

        // email message to receiver
    }

这是与控制器联系的Ajax方法:

$('#contactBtn').click(function () {
    var form = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', form).val();
    var message = quill.root.innerHTML; // <-- HTML formatted message

    $.ajax({
        url: "/Communication/Contact",
        data: { __RequestVerificationToken: token, message: message },
        dataType: 'json',
        type: "POST"
    });
});

因此上面的代码有效,但是我不确定这是否正确?上面的代码是否存在安全问题?我需要在HTML上进行任何编码吗?

2 个答案:

答案 0 :(得分:2)

实际上ValidateInput属性与XSS (Cross Site Security)问题有关。

XSS(跨站点安全性)是一种安全攻击,攻击者在输入数据时会注入恶意代码。此代码可以是javascript,vbscript或任何其他脚本代码。将代码注入最终用户的浏览器后。该代码可以运行并获得对cookie,会话,本地文件等的访问。

现在好消息是,默认情况下,ASP.NET MVC中禁止使用XSS。因此,如果有人尝试用输入来发布JavaScript或HTML代码,则他将出现以下错误。

  

从客户端检测到一个潜在危险的Request.Form值.....

但是在现实生活中,有些情况下必须允许HTML,例如HTML编辑器。因此,对于这种情况,我们使用ValidateInput属性装饰操作方法,如下所示:

[ValidateInput(false)]
public async Task<JsonResult> Contact(string message)
{

}

但是这样做有问题。我们允许HTML和脚本执行可能会很危险的完整操作。假设我们要发布的表单具有五个输入文本字段,现在所有五个文本字段都可以包含HTML和脚本。

相反,此Microsoft article建议:

  

对于ASP.NET MVC 3或更高版本的应用程序,当您需要将HTML发布回模型时,请不要使用ValidateInput(false)来关闭请求验证。只需将[AllowHtml]添加到模型属性中,如下所示:

public class BlogEntry
{
  public int UserId {get;set;}
  [AllowHtml]
  public string BlogText {get;set;}
}

底线是ValidateInput允许脚本和HTML在整个操作级别上发布,而AllowHTML在更细粒度的级别上。

有关更多详细信息,您可以阅读ASP.NET Security - Securing Your ASP.NET Applications

答案 1 :(得分:0)

在动作方法上使用[ValidateInput(false)]并不是一个好方法,因为如果我们传入模型,则可能会有其他输入参数未得到验证...使用[AllowHtml]可以工作。 ..

对于这种情况,我们可以按照this tutorial中的说明进行操作:

我的解决方案基于上面的教程,除了我在绑定器模型中添加了清理逻辑,这意味着我们允许HTML输入,但是使用HTMLSanitizer清理输入。

定义了自定义模型联编程序:

public class AllowHtmlBinder: IModelBinder
{
    // use HtmlSanitizer to remove unsafe HTML/JS from input
    private HtmlSanitizer _htmlSanitizer = new HtmlSanitizer();

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
        var name = bindingContext.ModelName;
        var unvalidatedInputMessage = request.Unvalidated[name]; // get the unvalidated input
        var sanitizedMessage = _htmlSanitizer.Sanitize(unvalidatedInputMessage); // removed script or any XSS thread from user input
        return sanitizedMessage;
    }
}

并将其用于特定参数:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Contact([ModelBinder(typeof(AllowHtmlBinder))] string message)
{
    if (!HttpContext.User.Identity.IsAuthenticated)
    {
        return Json(new { Authorize = "false" });
    }

    // email message to receiver
}