ASP.NET Core 8 Web API如何基于用户权限实现条件序列化?
ASP.NET Core 8 按用户套餐(Claims)统一过滤响应字段的方案
下面提供几种在ASP.NET Core 8中统一处理所有控制器响应、根据用户Claims移除指定字段的可行方案:
方案一:自定义ActionFilter全局过滤
通过创建全局Action过滤器,在响应返回前拦截并根据用户套餐Claims修改输出内容,这种方式直观易维护,适合大多数场景。
1. 实现自定义过滤器及配套Json转换器
using Microsoft.AspNetCore.Mvc.Filters; using System.Reflection; using System.Text.Json; // 全局响应字段过滤过滤器 public class FilterFieldsByPlanAttribute : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext context) { if (context.Result is ObjectResult objectResult && objectResult.Value != null) { var user = context.HttpContext.User; // 从Claims中获取用户套餐标识 var userPlan = user.FindFirstValue("UserPlan"); if (string.IsNullOrEmpty(userPlan)) return; // 定义套餐与需移除字段的映射规则 var fieldRules = new Dictionary<string, List<string>> { { "Basic", new List<string> { "PremiumFeature", "AdvancedAnalytics" } }, { "Pro", new List<string> { "EnterpriseSupport" } } }; if (fieldRules.TryGetValue(userPlan, out var fieldsToRemove)) { // 使用自定义Json转换器序列化,避免修改原对象 var options = new JsonSerializerOptions(JsonSerializerDefaults.Web); options.Converters.Add(new PlanBasedPropertyConverter(userPlan, fieldRules)); var filteredJson = JsonSerializer.Serialize(objectResult.Value, options); var filteredValue = JsonSerializer.Deserialize(filteredJson, objectResult.Value.GetType(), options); objectResult.Value = filteredValue; } } base.OnResultExecuting(context); } } // 基于套餐的Json序列化转换器 public class PlanBasedPropertyConverter : JsonConverter<object> { private readonly string _userPlan; private readonly Dictionary<string, List<string>> _fieldRules; public PlanBasedPropertyConverter(string userPlan, Dictionary<string, List<string>> fieldRules) { _userPlan = userPlan; _fieldRules = fieldRules; } public override bool CanConvert(Type typeToConvert) => !typeToConvert.IsPrimitive && !typeToConvert.IsEnum && typeToConvert != typeof(string); public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException("此转换器仅用于序列化输出"); public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { if (!_fieldRules.TryGetValue(_userPlan, out var fieldsToRemove)) { JsonSerializer.Serialize(writer, value, options); return; } writer.WriteStartObject(); foreach (var property in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!fieldsToRemove.Contains(property.Name)) { var propertyValue = property.GetValue(value); writer.WritePropertyName(property.Name); JsonSerializer.Serialize(writer, propertyValue, property.PropertyType, options); } } writer.WriteEndObject(); } }
2. 注册全局过滤器
在Program.cs中添加全局过滤器,让所有控制器生效:
builder.Services.AddControllers(options => { options.Filters.Add<FilterFieldsByPlanAttribute>(); });
方案二:自定义Json输出格式化器
如果需要更底层的序列化控制,可以替换默认的Json输出格式化器,所有Json响应都会经过该格式化器处理。
1. 实现自定义格式化器
using Microsoft.AspNetCore.Mvc.Formatters; using System.Text.Json; public class PlanBasedJsonOutputFormatter : SystemTextJsonOutputFormatter { public PlanBasedJsonOutputFormatter(JsonSerializerOptions options) : base(options) { } public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { var user = context.HttpContext.User; var userPlan = user.FindFirstValue("UserPlan"); if (string.IsNullOrEmpty(userPlan) || context.Object == null) { await base.WriteResponseBodyAsync(context, selectedEncoding); return; } var fieldRules = new Dictionary<string, List<string>> { { "Basic", new List<string> { "PremiumFeature", "AdvancedAnalytics" } }, { "Pro", new List<string> { "EnterpriseSupport" } } }; var modifiedOptions = new JsonSerializerOptions(SerializerOptions); modifiedOptions.Converters.Add(new PlanBasedPropertyConverter(userPlan, fieldRules)); var json = JsonSerializer.Serialize(context.Object, modifiedOptions); await context.HttpContext.Response.WriteAsync(json, selectedEncoding); } }
2. 替换默认格式化器
在Program.cs中替换默认的Json输出格式化器:
builder.Services.AddControllers(options => { // 移除默认的SystemTextJson格式化器 var defaultFormatter = options.OutputFormatters.OfType<SystemTextJsonOutputFormatter>().FirstOrDefault(); if (defaultFormatter != null) { options.OutputFormatters.Remove(defaultFormatter); } // 添加自定义格式化器 options.OutputFormatters.Add(new PlanBasedJsonOutputFormatter(new JsonSerializerOptions(JsonSerializerDefaults.Web))); });
方案三:模型内条件过滤(适合单个模型定制)
如果只需针对特定模型处理,可以在模型中添加过滤方法,再通过过滤器调用:
public class UserResponse { public string Id { get; set; } public string Name { get; set; } public string PremiumFeature { get; set; } public string EnterpriseSupport { get; set; } public void ApplyPlanFilter(string userPlan) { switch (userPlan) { case "Basic": PremiumFeature = null; EnterpriseSupport = null; break; case "Pro": EnterpriseSupport = null; break; } } }
然后在过滤器中调用该方法即可,这种方式灵活性较低,适合局部场景。
内容的提问来源于stack exchange,提问作者Christian Edel
相关产品推荐
相关产品推荐

