代码之家  ›  专栏  ›  技术社区  ›  Hooman Bahreini

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

  •  0
  • Hooman Bahreini  · 技术社区  · 7 年前

    enter image description here

    我可以得到HTML格式的文本,如下所示:

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

    现在我想把这个HTML格式的文本传递给我的控制器,我的控制器会把文本放到一封电子邮件中并发送给接收者。

    问题是HTML字符串被认为是不安全的,所以为了将它传递给我的控制器,我需要添加 [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 回复  |  直到 7 年前
        1
  •  2
  •   Hooman Bahreini    7 年前

    事实上 ValidateInput 属性与 XSS (Cross Site Security )问题。

    XSS(跨站点安全) 是一种安全攻击,攻击者在执行数据输入时插入恶意代码。此代码可以是javascript、vbscript或任何其他脚本代码。一旦代码被注入到最终用户浏览器中。此代码可以运行并访问cookie、会话、本地文件等。

    现在好消息是,在ASP.NET MVC中,XSS在默认情况下是被阻止的。因此,如果有人试图用输入发布JavaScript或HTML代码,他会出现以下错误。

    潜在的危险请求。从客户端检测到窗体值。。。。。

    但在现实生活中,有些场景必须允许使用HTML,比如HTML编辑器。所以对于那些场景我们用 属性如下:

    [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;}
    }
    

    所以底线是 验证输入 允许在整个操作级别发布脚本和HTML,同时 AllowHTML

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

        2
  •  0
  •   Hooman Bahreini    7 年前

    [ValidateInput(false)] 在操作方法上不是一个好的方法,因为可能有其他输入参数没有得到验证。。。使用 [AllowHtml]

    对于这个场景,我们可以做下面解释的事情 this tutorial

    我的解决方案基于上面的教程,除了我在model binder中添加了清理逻辑,这意味着我们允许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
    }
    
    推荐文章