Reputation: 25292
Some of my model properties are marked by AllowHtml attribute. Is there any way to automatically apply AntiXss protection (i. e. filter only allowed tags) to these fields?
Upvotes: 10
Views: 2210
Reputation: 32758
I would go for replacing those AllowHtml
attributes with RegularExpression
data-annotation validations. The advantage is by this way you can trap the error and show to the user what went wrong while the former one fires the error at a global level.
For ex.
public class MyViewModel
{
[DataType(DataType.MultilineText)]
[RegularExpression(@"^[^\<\>]*$", ErrorMessage = "May not contain <,>")]
public string Text { get; set; }
}
Upvotes: 1
Reputation: 6109
First, afaik, nothing is built-in for that. But MVC allows to do such things easily via custom ModelBinders, you could define your
public class CustomAntiXssAttribute : Attribute { }
and decorate your properties with it (and even inherit from AllowHtmlAttribute
if you wish). Then with a model binder you could add your specific anti-xss protection:
public class CutstomModelBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.Attributes.OfType<CustomAntiXssAttribute>().Any())
{
var valueResult = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
var filteredValue = SOME_CUSTOM_FILTER_FUNCTION_HERE(valueResult.AttemptedValue);
propertyDescriptor.SetValue(bindingContext.Model, filteredValue);
}
else // revert to the default behavior.
{
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
}
Then inside that SOME_CUSTOM_FILTER_FUNCTION_HERE
you could use what @Yogiraj suggested, or use a Regexp, or even apply HtmlAgilityPack-based filtering.
P.S. Don't forget to add ModelBinders.Binders.DefaultBinder = new CutstomModelBinder();
to Application_Start (I forgot :))
Upvotes: 10
Reputation: 33974
Untested Code,
public class ADefaultModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.RequestValidationEnabled)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
value = value.Replace("&", "");// replace existing & from the value
var encodedValue = Microsoft.Security.Application.Encoder.HtmlEncode(value);
bindingContext.ModelMetadata.RequestValidationEnabled = encodedValue.Contains("&"); // Whether AntiXss encoded a char to &..
}
return base.BindModel(controllerContext, bindingContext);
}
}
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
ModelBinders.Binders.DefaultBinder = new ADefaultModelBinder();
Upvotes: 0
Reputation: 1982
There is no automatic way. The closest you can do is to get AntiXss Nuget package. Then you can use it like below in your controller :
Microsoft.Security.Application.Sanitizer.GetSafeHtml("YourHtml");
OR
Microsoft.Security.Application.Encoder.HtmlEncode("YourHtml");
If you use you can decode it using
Server.HtmlDecode("HtmlEncodedString");
Hope this helps.
Upvotes: 4