将 html 标记从 jquery 发布调用发送到 asp.net 页面时,从客户端检测到潜在危险的 Request.QueryString 值

Posted

技术标签:

【中文标题】将 html 标记从 jquery 发布调用发送到 asp.net 页面时,从客户端检测到潜在危险的 Request.QueryString 值【英文标题】:A potentially dangerous Request.QueryString value was detected from the client when sending html markup from jquery post call to asp.net page 【发布时间】:2011-04-22 14:11:03 【问题描述】:

我正在使用 jQuery 对 ASP.NET 页面进行 ajax 调用,该页面充当我的 ajax 服务器页面,以将我发送给它的数据保存在查询字符串中。在 ASP.NET 页面中,当我尝试读取查询字符串时出现此错误:

A potentially dangerous Request.QueryString value was detected from the client...

我在我的页面中设置了ValidateRequest="false"。不想为所有页面设置它。在页面级别而不是配置级别也是如此:

  var content = "<h3>Sample header</h3><p>sample para</p>"
  content = encodeURIComponent(content);
  var url = "../Lib/ajaxhandler.aspx?mode=savecontent&page=home&ltxt=" + content;

     $.post(url, function (data)  
       //check return value and do something
   );

在我的 asp.net 页面中:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ajaxhandler.aspx.cs" ValidateRequest="false" Inherits="MyProject.Lib.ajaxhandler" %>

但是当我发送纯文本而不是 html 标记时,它工作正常。

【问题讨论】:

您完全确定您已将 ValidateRequest="false" 放在正确的页面上吗? 哦,是的。我仔细检查了。 ValidateRequest="false" doesn't work in Asp.Net 4的可能重复 【参考方案1】:

如果这是 ASP.NET 4,则有一个 breaking change 和 ValidateRequest。有关requestValidationMode 的更多信息,请参阅this *** question。

【讨论】:

哦,是的。当我将框架版本升级到 4.0 时出现了这个问题。昨天它与 2.0 一起工作。【参考方案2】:

已经有一个很好的答案,我将在这里提供信息,这样你就不必点击链接了。

运行 ASP.NET 4.0 时,您需要在 web.config 文件中设置以下内容RequestValidationMode="2.0"

这个属性有什么用?

一个值,指示使用哪个 ASP.NET 版本特定的方法 将使用验证。默认为 4.0。

那么可能的值是多少?

4.0(默认)。 HttpRequest 对象在内部设置了一个标志,指示应在任何时候触发请求验证 访问 HTTP 请求数据。这保证了请求 在 cookie 和 URL 等数据之前触发验证 在请求期间访问。 的请求验证设置 配置文件或@Page中的pages元素(如果有) 单个页面中的指令将被忽略。

2.0。请求验证仅对页面启用,并非对所有 HTTP 请求启用。另外,页面的请求验证设置 配置文件或@Page 指令中的元素(如果有) 在单个页面中用于确定哪些页面请求 验证。

Information citated from this msdn site.

【讨论】:

【参考方案3】:

如果您想为一个特定的 ASP.NET 页面或一个或多个查询字符串参数添加自定义验证逻辑,而不为整个页面设置 ValidateRequest="false" - 以下“hacky”解决方案可能很有用:

public partial class MyPage : System.Web.UI.Page

    private string SomeUnvalidatedValue  get; set; 

    public override void ProcessRequest(HttpContext context)
    
        var queryString = context.Request.QueryString;

        var readOnly = queryString.GetType().GetProperty("IsReadOnly",
            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        readOnly.SetValue(queryString, false);

        var unvalidatedValue = context.Request.Unvalidated.QueryString["SomeKey"];
        // for RequestValidationMode="2.0"
        //var unvalidatedValue = context.Request.QueryString["SomeKey"];

        // custom logic goes here

        // you could store unvalidated value here and then remove it from the query string
        SomeUnvalidatedValue = unvalidatedValue;
        queryString["SomeKey"] = string.Empty;
        // or just remove all "potentially dangerous" symbols, for example
        if (!string.IsNullOrEmpty(unvalidatedValue))
        
            queryString["SomeKey"] = Regex.Replace(unvalidatedValue,
                "(\\<+[a-z!/\\?])|(&\\#)", new MatchEvaluator((m) =>
                
                    return m.Value.Replace("<", string.Empty).Replace("&#", string.Empty);
                ), RegexOptions.IgnoreCase);
        

        readOnly.SetValue(queryString, true);

        // keep other request validation logic as is
        base.ProcessRequest(context);
    

作为这个 ASP.NET 方法分析结果的正则表达式:CrossSiteScriptingValidation.IsDangerousString

使用 .NET 4.5.2、IIS 集成模式测试的代码,有和没有RequestValidationMode="2.0"

【讨论】:

【参考方案4】:

我基于VAV's answer创建了几个可重用的方法

   public static string ExtractUnvalidatedValue(HttpRequest request, string key)
        
            var unvalidatedValue =  HttpUtility.UrlDecode(request.Unvalidated.QueryString[key]);
            // for RequestValidationMode="2.0"
            //var unvalidatedValue = context.Request.QueryString["SomeKey"];

          // remove all "potentially dangerous" symbols
            return ReplacePotentiallyDangerousSymbols(unvalidatedValue, string.Empty);
        

    public static string ReplacePotentiallyDangerousSymbols(string unvalidatedValue, string valueToReplace="")
        
            if (!string.IsNullOrEmpty(unvalidatedValue))
            
                //The regular expression made as result of this ASP.NET method analyzing: CrossSiteScriptingValidation.IsDangerousString http://referencesource.microsoft.com/#System.Web/CrossSiteScriptingValidation.cs,3c599cea73c5293b
                unvalidatedValue = Regex.Replace(unvalidatedValue,
                    "(\\<+[a-z!/\\?])|(&\\#)",
                    new MatchEvaluator((m) =>  return m.Value.Replace("<", valueToReplace).Replace("&#", valueToReplace); ), RegexOptions.IgnoreCase);
            
            return unvalidatedValue;
        

【讨论】:

【参考方案5】:

在我的情况下,不是 [HttpPost] 有 [HttpPost, ValidateInput(false)] 解决了这个问题。控制器动作代码示例如下:

[HttpPost, ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult UploadFile(HttpPostedFileBase blob)

     //your action code here

【讨论】:

【参考方案6】:

在 asp 页面的顶部设置 ValidateRequest="false"。

【讨论】:

以上是关于将 html 标记从 jquery 发布调用发送到 asp.net 页面时,从客户端检测到潜在危险的 Request.QueryString 值的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PHP 数据从数据库发送回 JQuery 并插入到表中

从jquery发送数据到wcf Web服务

使用来自 jquery 数据表的 ajax 调用发送参数

jQuery Mobile:将数据从一个页面发送到另一个页面

html 通过jQuery进行css样式注入。基本上调用body / head附加一个样式标记,你自己的css将添加一个新的标记和你的样式

jQuery - 使用 ajax 调用将 JSON 发送到 WCF 服务为空