如何在ASP.NET Core(.NET 5)中对JSON响应进行HTML编码?
解决方案:ASP.NET Core .NET5中JSON序列化默认HTML编码处理
一、为什么Newtonsoft的StringEscapeHandling.EscapeHtml不生效
你遇到的核心问题是混淆了JSON转义和HTML转义:
StringEscapeHandling.EscapeHtml仅将HTML特殊字符转成JSON的Unicode转义序列(比如<转成\u003C),客户端解析JSON后,得到的仍然是原始的<script>alert('evil');</script>字符串。- 当用jQuery的
.html()插入内容时,浏览器会把该字符串当成HTML解析执行,恶意脚本依然会运行。
我们需要的是HTML实体编码:把<转成<、>转成>等,这样客户端解析后得到的是实体字符串,插入HTML时会被当成纯文本渲染,不会执行脚本。
二、Newtonsoft.Json全局默认HTML编码方案
要实现序列化时自动对所有字符串做HTML编码,需自定义JsonConverter并全局注册:
1. 自定义HTML编码转换器
using System.Web; using Newtonsoft.Json; public class HtmlEncodedStringConverter : JsonConverter<string> { public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer) { // 反序列化时可选解码,按需调整 var value = reader.Value?.ToString(); return string.IsNullOrEmpty(value) ? value : HttpUtility.HtmlDecode(value); } public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } // 对字符串进行HTML编码后写入JSON writer.WriteValue(HttpUtility.HtmlEncode(value)); } }
2. 全局注册转换器
在Startup.cs中配置NewtonsoftJson时添加该转换器:
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews() .AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new HtmlEncodedStringConverter()); }); }
配置后,所有通过JsonResult返回的字符串属性都会自动被HTML编码,返回的JSON中ItemName会变成"<script>alert('evil');</script>",客户端用.html()插入时会显示纯文本,不会执行脚本。
三、System.Text.Json的处理方式
System.Text.Json默认不会对属性值做HTML编码,但同样可以通过自定义转换器实现全局处理:
1. 自定义HTML编码转换器
using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; public class HtmlEncodedStringConverter : JsonConverter<string> { public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var value = reader.GetString(); return string.IsNullOrEmpty(value) ? value : HtmlEncoder.Default.Decode(value); } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); return; } var encodedValue = HtmlEncoder.Default.Encode(value); writer.WriteStringValue(encodedValue); } }
2. 全局注册(若切换到System.Text.Json)
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new HtmlEncodedStringConverter()); }); }
补充说明
如果仅需对部分属性编码,可给特定属性添加[JsonConverter(typeof(HtmlEncodedStringConverter))]特性,无需全局注册。
另外,客户端也可改用.text()方法插入内容(而非.html()),但服务器端编码是更可靠的防护手段,尤其是无法完全控制客户端渲染逻辑时(比如使用Telerik库)。
内容的提问来源于stack exchange,提问作者LP13
相关产品推荐
相关产品推荐

