You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 7 API中间件实现参数脱敏:调试时隐藏敏感信息可行吗?

.NET 7 API 参数脱敏与自动还原方案

针对你的需求——调试时隐藏敏感参数明文,业务逻辑可自动还原,同时避免中间件导致的API不可用问题,以下是两种可行的实现方案:

方案一:自定义敏感属性+模型字段加密(简单直接)

通过在模型中封装敏感字段,对外暴露脱敏视图,内部存储加密后的明文,确保调试时无法查看真实内容。

1. 定义敏感字段标记属性

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

2. 改造请求模型

将敏感字段的getter返回脱敏字符串,setter存储加密后的内容,同时提供解密方法供业务逻辑调用:

public class LoginRequestMobile
{
    private string _encryptedPhone;
    private string _encryptedPassword;
    private readonly IEncryptionService _encryptionService;

    // 构造函数注入加密服务(需在Program.cs注册)
    public LoginRequestMobile(IEncryptionService encryptionService)
    {
        _encryptionService = encryptionService;
    }

    [SensitiveData]
    public string PhoneNumber
    {
        get => "******";
        set => _encryptedPhone = _encryptionService.Encrypt(value);
    }

    [SensitiveData]
    public string Password
    {
        get => "******";
        set => _encryptedPassword = _encryptionService.Encrypt(value);
    }

    // 供业务逻辑获取明文的方法
    public string GetDecryptedPhone() => _encryptionService.Decrypt(_encryptedPhone);
    public string GetDecryptedPassword() => _encryptionService.Decrypt(_encryptedPassword);
}

3. 实现加密服务

以AES加密为例,实现基础的加解密逻辑:

public interface IEncryptionService
{
    string Encrypt(string plainText);
    string Decrypt(string cipherText);
}

public class AesEncryptionService : IEncryptionService
{
    private readonly byte[] _key;
    private readonly byte[] _iv;

    public AesEncryptionService(IConfiguration config)
    {
        // 从配置文件读取密钥(切勿硬编码)
        _key = Encoding.UTF8.GetBytes(config["Encryption:Key"]);
        _iv = Encoding.UTF8.GetBytes(config["Encryption:IV"]);
    }

    public string Encrypt(string plainText)
    {
        using var aes = Aes.Create();
        aes.Key = _key;
        aes.IV = _iv;
        var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        
        using var ms = new MemoryStream();
        using var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
        using var sw = new StreamWriter(cs);
        
        sw.Write(plainText);
        sw.Flush();
        cs.FlushFinalBlock();
        
        return Convert.ToBase64String(ms.ToArray());
    }

    public string Decrypt(string cipherText)
    {
        using var aes = Aes.Create();
        aes.Key = _key;
        aes.IV = _iv;
        var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        
        using var ms = new MemoryStream(Convert.FromBase64String(cipherText));
        using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
        using var sr = new StreamReader(cs);
        
        return sr.ReadToEnd();
    }
}

4. 注册服务

在Program.cs中注入加密服务:

builder.Services.AddScoped<IEncryptionService, AesEncryptionService>();

5. 业务逻辑中使用

public async Task<ApiOperationResult<Token>> Login(LoginRequestMobile userLogin)
{
    // 获取解密后的明文
    var phone = userLogin.GetDecryptedPhone();
    var password = userLogin.GetDecryptedPassword();
    
    // 后续验证、生成Token逻辑
}

方案二:自定义JsonConverter(适配JSON请求场景)

如果你的API主要接收JSON请求,使用JsonConverter可以在反序列化阶段自动加密敏感字段,序列化(包括调试视图)时返回脱敏内容,无需修改模型的属性封装。

1. 定义敏感属性(同方案一)

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

2. 实现JsonConverter

public class SensitiveDataConverter : JsonConverter<string>
{
    private readonly IEncryptionService _encryptionService;

    public SensitiveDataConverter(IEncryptionService encryptionService)
    {
        _encryptionService = encryptionService;
    }

    // 反序列化:将请求中的明文加密后存入模型
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var plainText = reader.GetString();
        return string.IsNullOrEmpty(plainText) ? plainText : _encryptionService.Encrypt(plainText);
    }

    // 序列化:调试/日志输出时返回脱敏内容
    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        writer.WriteStringValue("******");
    }
}

3. 配置模型与服务

在请求模型的敏感字段上标记转换器:

public class LoginRequestMobile
{
    [SensitiveData]
    [JsonConverter(typeof(SensitiveDataConverter))]
    public string PhoneNumber { get; set; }

    [SensitiveData]
    [JsonConverter(typeof(SensitiveDataConverter))]
    public string Password { get; set; }
}

在Program.cs中注册加密服务和JsonConverter:

builder.Services.AddScoped<IEncryptionService, AesEncryptionService>();

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 注入加密服务到转换器
        var encryptionService = builder.Services.BuildServiceProvider().GetRequiredService<IEncryptionService>();
        options.JsonSerializerOptions.Converters.Add(new SensitiveDataConverter(encryptionService));
    });

4. 业务逻辑使用

public async Task<ApiOperationResult<Token>> Login(LoginRequestMobile userLogin, IEncryptionService encryptionService)
{
    var phone = encryptionService.Decrypt(userLogin.PhoneNumber);
    var password = encryptionService.Decrypt(userLogin.Password);
    
    // 业务逻辑
}

关键注意事项

  • 密钥安全:加密密钥必须通过配置文件、密钥管理服务存储,禁止硬编码到代码中。
  • 避免中间件陷阱:之前中间件导致API不可用,大概率是直接修改了原始请求体的字节流,破坏了JSON格式。上述方案在序列化/模型绑定层面处理,不会损坏请求结构。
  • 调试防护:两种方案均确保调试时查看模型属性只能看到脱敏字符串,加密后的内容无法直接识别,彻底阻断开发者获取明文的路径。

内容的提问来源于stack exchange,提问作者Taha İbrahim Orhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 17:38:14