gpt4 book ai didi

c# - 如何使用反 xss 攻击清理 web api 中的输入数据

转载 作者:太空狗 更新时间:2023-10-29 21:33:05 27 4
gpt4 key购买 nike

下面是我的代码片段

模型类

//客户.cs

using CommonLayer;

namespace Models
{
public class Customer
{
public int Id { get; set; }

[MyAntiXss]
public string Name { get; set; }
}
}

我想清理模型类的“名称”字段中的值,如下所示

//CutstomModelBinder.cs

 using Microsoft.Security.Application;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;

namespace CommonLayer
{
public class CutstomModelBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.Attributes.OfType<MyAntiXssAttribute>().Any())
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
string filteredValue = Encoder.HtmlEncode(valueResult.AttemptedValue);
propertyDescriptor.SetValue(bindingContext.Model, filteredValue);
}
else
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
}

我将“DefaultBinder”更改为我的“CutstomModelBinder”,如下所示

//全局.asax.cs

using CommonLayer;
using System.Web.Http;
using System.Web;
using System.Web.Mvc;

namespace WebAPI
{
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
ModelBinders.Binders.DefaultBinder = new CutstomModelBinder();
}
}
}

我写了一个 Controller 类如下

//客户 Controller .cs

using Models;
using System.Collections.Generic;
using System.Web.Http;

namespace WebAPI.Controllers
{
public class CustomerController : ApiController
{
public string Post([FromBody]Customer customer)
{
//customer.Name = Encoder.HtmlEncode(customer.Name);
return string.Format("Id = {0}, Name = '{1}'", customer.Id, customer.Name);
}
}
}

当我如下调用上述 Controller 类的“Post”方法时,它会按预期调用 Controller 类的“Post”方法。但它没有在我的“CutstomModelBinder”类中调用“BindProperty”方法。

//程序.cs

using Models;
using System;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;

namespace Client
{
public static class Program
{
public static void Main(params string[] args)
{
bool success = Post();
Console.WriteLine("success = " + success);
Console.Read();
}

private static HttpClient GetHttpClient()
{
HttpClient client = new HttpClient { BaseAddress = new Uri("http://localhost:49295/") };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}

private static bool Post()
{
Customer customer = new Customer { Id = 1, Name = "<br>Anivesh</br>" };
HttpContent content = new ObjectContent<Customer>(customer, new JsonMediaTypeFormatter());

HttpClient client = GetHttpClient();
HttpResponseMessage response = client.PostAsync("Customer", content).Result;
client.Dispose();

if (response.IsSuccessStatusCode)
{
string expected = string.Format("Id = {0}, Name = '{1}'", customer.Id, customer.Name);
string result = response.Content.ReadAsAsync<string>().Result;
return expected == result;
}
else
return false;
}
}
}

请让我知道使用“DataBinders”的正确方法,以便我可以在 Controller 中接收调用之前在一个公共(public)位置清理输入数据。

最佳答案

要使用 Web API 以通用方式清理输入,您可以按照我之前的回答中所述创建自己的 ModelBinder,但是更简单的方法可能是修改现有的 JsonMediaTypeFormatter 以在 中包含所需的清理逻辑ReadFromStreamAsync 方法。

您可以尝试的一种方法如下:

首先,创建一个通用属性,用于装饰 DTO 中需要清理的属性,即:

 [AttributeUsage(AttributeTargets.Property)]
public sealed class SanitizeAttribute : Attribute
{ }

然后创建 JsonMediaTypeFormatter 的子类型,负责清理,即:

public sealed class SanitizingJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
Task<object> resultTask = base.ReadFromStreamAsync(type, readStream, content, formatterLogger, cancellationToken);

var propertiesFlaggedForSanitization = type.GetProperties().Where(e => e.GetCustomAttribute<SanitizeAttribute>() != null).ToList();
if (propertiesFlaggedForSanitization.Any())
{
var result = resultTask.Result;
foreach (var propertyInfo in propertiesFlaggedForSanitization)
{
var raw = (string)propertyInfo.GetValue(result);
if (!string.IsNullOrEmpty(raw))
{
propertyInfo.SetValue(result, AntiXssEncoder.HtmlEncode(raw, true));
}
}
}
return resultTask;
}
}

此实现只是检查生成的类型是否具有任何用 Sanitize 属性修饰的属性,如果是,则使用内置的 System.Web.Security.AntiXss.AntiXssEncoder(.NET 4.5 及更高版本)来执行 sanitizer 。

您可能希望优化此类,以便它缓存类型和属性信息,这样您就不会在每次反序列化时都进行重量级反射调用。

该过程的最后一步是在 WebAPI 启动代码中用您自己的格式替换内置的 JSON 媒体类型:

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
config.Formatters.Remove(jsonFormatter);
config.Formatters.Add(new SanitizingJsonMediaTypeFormatter());

现在,任何具有用 Sanitize 属性修饰的属性的 DTO 都将在 DTO 到达您的 Controller 之前被正确编码。

关于c# - 如何使用反 xss 攻击清理 web api 中的输入数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32599961/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com