Rad*_*094 1437 asp.net validation asp.net-mvc html-encode request.form
每当用户在我的Web应用程序中发布包含<或>在页面中的内容时,我都会抛出此异常.
我不想进入关于抛出异常或崩溃整个Web应用程序的聪明性的讨论,因为有人在文本框中输入了一个字符,但我正在寻找一种优雅的方法来处理这个问题.
捕获异常并显示
发生错误请返回并重新输入整个表单,但这次请不要使用<
对我来说似乎不够专业.
禁用post validation(validateRequest="false")肯定会避免此错误,但它会使页面容易受到许多攻击.
理想情况:当发回包含HTML限制字符的回发时,Form集合中的已发布值将自动进行HTML编码.所以.Text我的文本框的属性将是something & lt; html & gt;
有没有办法可以从处理程序中执行此操作?
Jac*_*esB 1065
我认为你是通过尝试编码所有发布的数据从错误的角度攻击它.
请注意," <"也可能来自其他外部源,如数据库字段,配置,文件,订阅源等.
此外," <"本身并不危险.它在特定的上下文中是危险的:当编写未编码为HTML输出的字符串时(因为XSS).
在其他情况下,不同的子字符串是危险的,例如,如果您将用户提供的URL写入链接,则子字符串" javascript:"可能是危险的.另一方面,单引号字符在SQL查询中插入字符串时很危险,但如果它是从表单提交的名称的一部分或从数据库字段读取,则非常安全.
底线是:您无法过滤危险字符的随机输入,因为在适当的情况下任何字符都可能是危险的.您应该在某些特定字符可能变得危险的位置进行编码,因为它们会跨越到具有特殊含义的不同子语言.将字符串写入HTML时,应使用Server.HtmlEncode对HTML中具有特殊含义的字符进行编码.如果将字符串传递给动态SQL语句,则应编码不同的字符(或者更好,让框架通过使用预处理语句等为您完成).
如果您确定在任何地方进行HTML编码,则将字符串传递给HTML,然后在文件validateRequest="false"中的<%@ Page ... %>指令中进行设置.aspx.
在.NET 4中,您可能需要做更多的事情.有时也需要添加<httpRuntime requestValidationMode="2.0" />到web.config(引用).
Zac*_*son 499
如果您使用的是ASP.NET MVC,则会出现此错误的不同解决方案:
C#样本:
[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
Visual Basic示例:
<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
...
End Function
Run Code Online (Sandbox Code Playgroud)
Ant*_*ton 405
在ASP.NET MVC(从版本3开始)中,您可以将AllowHtml属性添加到模型的属性中.
它允许请求在模型绑定期间通过跳过属性的请求验证来包含HTML标记.
[AllowHtml]
public string Description { get; set; }
Run Code Online (Sandbox Code Playgroud)
Jor*_*anC 213
如果您使用的是.NET 4.0,请确保将其添加到标记内的web.config文件中<system.web>:
<httpRuntime requestValidationMode="2.0" />
Run Code Online (Sandbox Code Playgroud)
在.NET 2.0中,请求验证仅应用于aspx请求.在.NET 4.0中,这扩展到包括所有请求.您可以通过指定以下内容恢复为仅在处理时执行XSS验证.aspx:
requestValidationMode="2.0"
Run Code Online (Sandbox Code Playgroud)
您可以通过指定完全禁用请求验证:
validateRequest="false"
Run Code Online (Sandbox Code Playgroud)
Car*_*lin 112
对于ASP.NET 4.0,您可以通过将标记全部放在<location>元素中来允许标记作为特定页面的输入而不是整个站点.这将确保您的所有其他页面都是安全的.您不需要放入ValidateRequest="false".aspx页面.
<configuration>
...
<location path="MyFolder/.aspx">
<system.web>
<pages validateRequest="false" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
</location>
...
</configuration>
Run Code Online (Sandbox Code Playgroud)
在web.config中控制它更安全,因为您可以在站点级别看到哪些页面允许标记作为输入.
您仍然需要以编程方式验证禁用请求验证的页面上的输入.
gli*_*ran 71
之前的答案很棒,但没有人说过如何排除单个字段的HTML/JavaScript注入验证.我不知道以前的版本,但在MVC3 Beta中你可以这样做:
[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
...
}
Run Code Online (Sandbox Code Playgroud)
这仍然验证除被排除的字段之外的所有字段.关于这一点的好处是你的验证属性仍然验证字段,但你只是没有得到"从客户端检测到一个潜在危险的Request.Form值"异常.
我用它来验证正则表达式.我已经创建了自己的ValidationAttribute来查看正则表达式是否有效.由于正则表达式可以包含类似于我应用上述代码的脚本的东西 - 正则表达式仍在被检查是否有效,但如果它包含脚本或HTML则不然.
ran*_*sen 51
在ASP.NET MVC中,您需要在web.config中设置requestValidationMode ="2.0"和validateRequest ="false",并将ValidateInput属性应用于您的控制器操作:
<httpRuntime requestValidationMode="2.0"/>
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
Run Code Online (Sandbox Code Playgroud)
和
[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
...
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*dox 42
您可以在Global.asax中捕获该错误.我仍然想验证,但显示适当的消息.在下面列出的博客上,可以获得这样的示例.
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (ex is HttpRequestValidationException)
{
Response.Clear();
Response.StatusCode = 200;
Response.Write(@"[html]");
Response.End();
}
}
Run Code Online (Sandbox Code Playgroud)
重定向到另一个页面似乎也是对异常的合理响应.
http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html
小智 36
这个问题的答案很简单:
var varname = Request.Unvalidated["parameter_name"];
Run Code Online (Sandbox Code Playgroud)
这将禁用特定请求的验证.
小智 34
请记住,某些.NET控件会自动对输出进行HTML编码.例如,在TextBox控件上设置.Text属性将自动对其进行编码.这特别意味着转换<成<,>进入>和&进入&.所以要小心这样做......
myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code
Run Code Online (Sandbox Code Playgroud)
但是,HyperLink,Literal和Label的.Text属性不会对HTML进行编码,因此包装Server.HtmlEncode(); 如果您想阻止<script> window.location = "http://www.google.com"; </script>输出到您的页面并随后执行,那么必须在这些属性上设置任何内容.
做一些实验,看看什么编码,什么不编码.
Mah*_*kar 29
在web.config文件中,在标记内插入带有属性requestValidationMode ="2.0"的httpRuntime元素.还要在pages元素中添加validateRequest ="false"属性.
例:
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
<pages validateRequest="false">
</pages>
</configuration>
Run Code Online (Sandbox Code Playgroud)
小智 24
如果您不想禁用ValidateRequest,则需要实现JavaScript函数以避免异常.它不是最佳选择,但它有效.
function AlphanumericValidation(evt)
{
var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
((evt.which) ? evt.which : 0));
// User type Enter key
if (charCode == 13)
{
// Do something, set controls focus or do anything
return false;
}
// User can not type non alphanumeric characters
if ( (charCode < 48) ||
(charCode > 122) ||
((charCode > 57) && (charCode < 65)) ||
((charCode > 90) && (charCode < 97))
)
{
// Show a message or do something
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在代码后面的PageLoad事件中,使用下一个代码将属性添加到控件:
Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
Run Code Online (Sandbox Code Playgroud)
Pie*_*rcy 21
似乎没有人提到下面的内容,但它解决了我的问题.在任何人说是的之前它是Visual Basic ...哎呀.
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>
Run Code Online (Sandbox Code Playgroud)
我不知道是否有任何缺点,但对我来说这真的很棒.
Sel*_*Sel 19
另一种解决方案是
protected void Application_Start()
{
...
RequestValidator.Current = new MyRequestValidator();
}
public class MyRequestValidator: RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
if (!result)
{
// Write your validation here
if (requestValidationSource == RequestValidationSource.Form ||
requestValidationSource == RequestValidationSource.QueryString)
return true; // Suppress error message
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
Dur*_*dey 15
如果您使用的是框架4.0,那么web.config中的条目(<pages validateRequest ="false"/>)
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
Run Code Online (Sandbox Code Playgroud)
如果您使用的是框架4.5,那么web.config中的条目(requestValidationMode ="2.0")
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>
Run Code Online (Sandbox Code Playgroud)
如果你只想要单页,那么在你的aspx文件中你应该把第一行作为:
<%@ Page EnableEventValidation="false" %>
Run Code Online (Sandbox Code Playgroud)
如果您已经有类似<%@ Page的内容,那么只需添加其余的=> EnableEventValidation="false"%>
我建议不要这样做.
Jai*_*der 13
在ASP.NET中,您可以捕获异常并对其执行某些操作,例如显示友好消息或重定向到另一个页面...还有可能您可以自己处理验证...
显示友好消息:
protected override void OnError(EventArgs e)
{
base.OnError(e);
var ex = Server.GetLastError().GetBaseException();
if (ex is System.Web.HttpRequestValidationException)
{
Response.Clear();
Response.Write("Invalid characters."); // Response.Write(HttpUtility.HtmlEncode(ex.Message));
Response.StatusCode = 200;
Response.End();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
原因
默认情况下,ASP.NET会验证可能导致跨站点脚本(XSS)和SQL注入的潜在不安全内容的所有输入控件.因此,通过抛出上述异常,它不允许这样的内容.默认情况下,建议允许在每次回发时进行此检查.
解
在许多情况下,您需要通过Rich TextBoxes或Rich Text Editors向页面提交HTML内容.在这种情况下,您可以通过将@Page指令中的ValidateRequest标记设置为false 来避免此异常.
<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>
Run Code Online (Sandbox Code Playgroud)
这将禁用对已将ValidateRequest标志设置为false的页面的请求的验证.如果要禁用此功能,请检查整个Web应用程序; 您需要在web.config <system.web>部分将其设置为false
<pages validateRequest ="false" />
Run Code Online (Sandbox Code Playgroud)
对于.NET 4.0或更高版本的框架,您还需要在<system.web>部分中添加以下行以完成上述工作.
<httpRuntime requestValidationMode = "2.0" />
Run Code Online (Sandbox Code Playgroud)
而已.我希望这可以帮助你摆脱上述问题.
引用者:ASP.Net错误:从客户端检测到一个潜在危险的Request.Form值
mag*_*tte 10
这里的其他解决方案都很不错,但是后面必须将[AllowHtml]应用于每个Model属性,这是一个很大的痛苦,特别是如果你在一个体面的网站上有超过100个模型.
如果像我一样,你想在网站范围内转换这个(恕我直言相当毫无意义)功能,你可以覆盖基本控制器中的Execute()方法(如果你还没有基本控制器我建议你做一个,它们可以是应用常用功能非常有用).
protected override void Execute(RequestContext requestContext)
{
// Disable requestion validation (security) across the whole site
ValidateRequest = false;
base.Execute(requestContext);
}
Run Code Online (Sandbox Code Playgroud)
只要确保你是HTML编码从用户输入的视图中抽出的所有内容(无论如何,它是带有Razor的ASP.NET MVC 3中的默认行为,所以除非出于某些奇怪的原因你使用的是Html.Raw()不应该要求此功能.
小智 10
我找到了一个使用JavaScript对数据进行编码的解决方案,该解决方案在.NET中解码(并且不需要jQuery).
将以下JavaScript函数添加到标题中.
function boo(){targetText = document.getElementById("HiddenField1"); sourceText = document.getElementById("userbox"); targetText.value = escape(sourceText.innerText); }在你的textarea中,包含一个调用boo()的onchange:
<textarea id="userbox" onchange="boo();"></textarea>
Run Code Online (Sandbox Code Playgroud)
最后,在.NET中,使用
string val = Server.UrlDecode(HiddenField1.Value);
Run Code Online (Sandbox Code Playgroud)
我知道这是单向的 - 如果你需要双向,你必须要有创意,但如果你不能编辑web.config,这就提供了一个解决方案.
这是我(MC9000)提出并通过jQuery使用的一个例子:
$(document).ready(function () {
$("#txtHTML").change(function () {
var currentText = $("#txtHTML").text();
currentText = escape(currentText); // Escapes the HTML including quotations, etc
$("#hidHTML").val(currentText); // Set the hidden field
});
// Intercept the postback
$("#btnMyPostbackButton").click(function () {
$("#txtHTML").val(""); // Clear the textarea before POSTing
// If you don't clear it, it will give you
// the error due to the HTML in the textarea.
return true; // Post back
});
});
Run Code Online (Sandbox Code Playgroud)
标记:
<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />
Run Code Online (Sandbox Code Playgroud)
这非常有效.如果黑客试图通过绕过JavaScript发布,他们只会看到错误.您也可以保存在数据库中编码的所有这些数据,然后将其(在服务器端)取消它,并在显示在其他地方之前解析并检查攻击.
禁用页面验证,如果你真的需要像,特殊字符>,<等等.然后确保显示的用户输入时,该数据是HTML编码.
页面验证存在安全漏洞,因此可以绕过它.此外,不应仅依赖页面验证.
请参阅:http://web.archive.org/web/20080913071637/http : //www.procheckup.com : 80/ PDFs/ bypassing-dot-NET-ValidateRequest.pdf
我也得到了这个错误.
在我的例子中,用户á在角色名称中输入了重音字符(关于ASP.NET成员资格提供者).
我将角色名称传递给一个方法,以便将用户授予该角色,并且$.ajax帖子请求失败了......
我这样做是为了解决问题:
代替
data: { roleName: '@Model.RoleName', users: users }
Run Code Online (Sandbox Code Playgroud)
做这个
data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }
Run Code Online (Sandbox Code Playgroud)
@Html.Raw 做了伎俩.
我将角色名称作为HTML值roleName="Cadastro bás".áASP.NET MVC阻止了HTML实体的这个值.现在我roleName按照应该的方式获取参数值:roleName="Cadastro Básico"ASP.NET MVC引擎不再阻止请求.
您还可以使用JavaScript的转义(字符串)函数来替换特殊字符.然后服务器端使用Server.URLDecode(字符串)将其切换回来.
这样您就不必关闭输入验证,其他程序员可以更清楚地知道字符串可能包含HTML内容.
小智 7
我最终在每次回发之前使用JavaScript来检查你不想要的字符,例如:
<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />
function checkFields() {
var tbs = new Array();
tbs = document.getElementsByTagName("input");
var isValid = true;
for (i=0; i<tbs.length; i++) {
if (tbs(i).type == 'text') {
if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
alert('<> symbols not allowed.');
isValid = false;
}
}
}
return isValid;
}
Run Code Online (Sandbox Code Playgroud)
当然,我的页面主要是数据输入,并且很少有元素可以进行回发,但至少保留了他们的数据.
您可以使用以下内容:
var nvc = Request.Unvalidated().Form;
Run Code Online (Sandbox Code Playgroud)
后来,nvc["yourKey"]应该工作。
您可以在自定义 Model Binder 中自动对字段进行 HTML 编码。我的解决方案有些不同,我将错误放在 ModelState 中并在字段附近显示错误消息。很容易修改此代码以进行自动编码
public class AppModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
try
{
return base.CreateModel(controllerContext, bindingContext, modelType);
}
catch (HttpRequestValidationException e)
{
HandleHttpRequestValidationException(bindingContext, e);
return null; // Encode here
}
}
protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
{
try
{
return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
}
catch (HttpRequestValidationException e)
{
HandleHttpRequestValidationException(bindingContext, e);
return null; // Encode here
}
}
protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
{
var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
if (valueProviderCollection != null)
{
ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
}
string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
bindingContext.ModelMetadata.DisplayName);
bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
}
}
Run Code Online (Sandbox Code Playgroud)
在应用程序_启动中:
ModelBinders.Binders.DefaultBinder = new AppModelBinder();
Run Code Online (Sandbox Code Playgroud)
请注意,它仅适用于表单字段。危险值不会传递到控制器模型,而是存储在 ModelState 中,并且可以在带有错误消息的表单上重新显示。
URL中的危险字符可以这样处理:
private void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
HttpContext httpContext = HttpContext.Current;
HttpException httpException = exception as HttpException;
if (httpException != null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
var httpCode = httpException.GetHttpCode();
switch (httpCode)
{
case (int)HttpStatusCode.BadRequest /* 400 */:
if (httpException.Message.Contains("Request.Path"))
{
httpContext.Response.Clear();
RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
requestContext.RouteData.Values["action"] ="InvalidUrl";
requestContext.RouteData.Values["controller"] ="Error";
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(requestContext, "Error");
controller.Execute(requestContext);
httpContext.Server.ClearError();
Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
}
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
错误控制器:
public class ErrorController : Controller
{
public ActionResult InvalidUrl()
{
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
只要这些只是“ <”和“>”(而不是双引号本身)字符,并且您在像 <input value=" this " /> 这样的上下文中使用它们,您就是安全的(而对于 <textarea >这一个</textarea> 当然你会很容易受到攻击)。这可能会简化您的情况,但对于更多情况,请使用其他发布的解决方案之一。
对于那些没有使用模型绑定的人,他们正在从 Request.Form 中提取每个参数,他们确信输入的文本不会造成伤害,还有另一种方法。不是一个很好的解决方案,但它会完成这项工作。
从客户端,将其编码为 uri 然后发送。
例如:
encodeURIComponent($("#MsgBody").val());
Run Code Online (Sandbox Code Playgroud)
从服务器端,接受它并将其解码为 uri。
例如:
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) :
null;
Run Code Online (Sandbox Code Playgroud)
或者
string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) :
null;
Run Code Online (Sandbox Code Playgroud)
请寻找UrlDecode和之间的差异UnescapeDataString
validateRequest="false"
就我而言,使用 asp:Textbox 控件 (Asp.net 4.5),而不是设置我使用的所有页面
<asp:TextBox runat="server" ID="mainTextBox"
ValidateRequestMode="Disabled"
></asp:TextBox>
Run Code Online (Sandbox Code Playgroud)
在导致异常的文本框中。
| 归档时间: |
|
| 查看次数: |
937699 次 |
| 最近记录: |