Web开发中不可避免的要防止XSS,防止XSS当然要进行Encode(这里是广义,表示Encode和过滤掉特殊标签,下面不再解释),分为输出和输入。各有用处,比如,您提交保存并显示一块内容,那么多数情况下,您需要对输出进行Encode;对于搜索功能,您需要对查询条件进行(输入)Encode,例如:当在查询参数里面输入<scrpit>之类的东西时候您可能需要去掉它,得到所谓安全的参数,也就是查询id=111和查询id=111><script>出来的结果是一样的。我今天暂时尝试了对输入进行Encode。
MVC里面有一个机制非常有用,您可以利用它完成很多事情---ModelBinder。一个场景如下:注册账户(为了简单,仅仅有用户名和密码两个字段)。
public class User
{
public string UserName { get; set; }
public string PassWord { get; set; }
}
我们需要对post到action里面的内容进行Encode。利用ModerBinder,我们可以绑定参数值,当然我们重写一个ModerBinder,就可以进行Encode了。

public class ForbiddenXSSModelBinder : IModelBinder
{
#region IModelBinder 成员
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == null)
return null;
return Encoder.HtmlEncode(valueProviderResult.AttemptedValue);
}
#endregion
}
这里忽略了异常处理,和一些入口检查。简单的代码,完成了功能。
很快问题出来了:
1、我们对所以的参数都进行Encode,这是不对的。因为有些我们是不需要过滤(有些是不能,比如PassWord字段),比如创建时间字段
2、对所有字段进行Encode无疑是浪费性能的事情
那么,我们能不能根据定制进行Encode呢?我想到了Attribute,思路如下:
1、我们对User类需要Encode的属性进行标识
2、在ModerBinder的时候对类型的属性进行判断,进行确定是否要Encode
思路有了,代码实现很简单。先定义一个Attribute:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class AllowEncodeAttribute : Attribute
{
/// <summary>
/// 判断是否需要Encode
/// </summary>
public bool AllowEncode { get; set; }
public AllowEncodeAttribute(bool allow)
{
AllowEncode = allow;
}
}
将User类更改:
[AllowEncode(true)]
public string UserName { get; set; }
在ModerBinder中这样操作:

public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
DealInputValue(controllerContext.HttpContext.Request.QueryString);
DealInputValue(controllerContext.HttpContext.Request.Form);
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == null)
return null;
Type type = bindingContext.ModelMetadata.ContainerType;
var propertyInfo = type.GetProperty(bindingContext.ModelName);
var attribute = Attribute.GetCustomAttribute(propertyInfo,
typeof(AllowEncodeAttribute)) as AllowEncodeAttribute;
if (attribute != null && attribute.AllowEncode == true)
{
return Encoder.HtmlEncode(valueProviderResult.AttemptedValue);
}
return valueProviderResult.AttemptedValue;
}
至此,尝试便结束了,初步达到了要求。
依然有一些问题存在:
1、对于参数并没有经过ModerBinder的我们怎么办?需要一个一个的Encode吗?
2、对于输出需要进行Encode的我们要如何?用HtmlHelper的Encode方法操作吗?
这是我下面要进行尝试的东西。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构