RuoVea.ExFilter 10.0.0.3

dotnet add package RuoVea.ExFilter --version 10.0.0.3
                    
NuGet\Install-Package RuoVea.ExFilter -Version 10.0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RuoVea.ExFilter" Version="10.0.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RuoVea.ExFilter" Version="10.0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="RuoVea.ExFilter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RuoVea.ExFilter --version 10.0.0.3
                    
#r "nuget: RuoVea.ExFilter, 10.0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RuoVea.ExFilter@10.0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RuoVea.ExFilter&version=10.0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=RuoVea.ExFilter&version=10.0.0.3
                    
Install as a Cake Tool

📋 RuoVea.ExFilter 组件概览

RuoVea.ExFilter 是一个功能全面的 ASP.NET Core 过滤器组件,提供全局异常处理、请求日志、参数验证、API安全校验等企业级功能。

🏗️ 核心功能架构

1. 全局异常处理 (ExceptionSetup)

配置方式
// 方式一:默认配置
builder.Services.ExceptionSetup();

// 方式二:通过 Action 配置
builder.Services.ExceptionSetup(options =>
{
    options.Enabled = true;
    options.LogToFile = false;
    options.LogMore = false;
});

// 方式三:通过配置文件
builder.Services.ExceptionSetup(builder.Configuration.GetSection("AopOption:ExceptionLog"));
配置文件
{
  "ExceptionLog": {
    "Enabled": true,
    "LogToFile": false,
    "LogMore": false
  }
}

2. 请求日志拦截 (RequestActionSetup)

配置方式
// 默认配置
builder.Services.RequestActionSetup();

// 自定义配置
builder.Services.RequestActionSetup(options =>
{
    options.Enabled = true;
    options.LogToFile = false;
    options.LogMore = false;
    options.IgnoreApis = "/health,/metrics";
});

// 配置文件方式
builder.Services.RequestActionSetup(builder.Configuration.GetSection("AopOption:RequestLog"));
配置文件
{
  "RequestLog": {
    "Enabled": true,
    "LogToFile": false,
    "LogMore": false,
    "IgnoreApis": "/health,/metrics"
  }
}

3. 资源过滤 (ResourceSetup)

// 对资源型信息进行过滤,常用于防盗链/资源缓存
builder.Services.ResourceSetup();

4. 统一结果格式化 (ResultSetup)

// 对 API 返回结果进行统一格式化
builder.Services.ResultSetup();

5. API 安全校验 (ApISafeSetup)

配置方式
// 接口安全校验
builder.Services.ApISafeSetup(options =>
{
    options.AppKeys = "key1,key2,key3";
    options.AppKeyName = "appKey";
    options.TimeStampName = "timeStamp";
    options.ExpiresMinute = 2;
});

// 配置文件方式
builder.Services.ApISafeSetup(builder.Configuration.GetSection("AopOption:ApISafe"));
配置文件
{
  "ApISafe": {
    "AppKeys": "key1,key2,key3",
    "AppKeyName": "appKey",
    "TimeStampName": "timeStamp", 
    "ExpiresMinute": 2
  }
}

6. 签名验证 (ApISignSetup)

配置方式
// 签名验证 MD5(appKey + signKey + timeStamp + data)
builder.Services.ApISignSetup(options =>
{
    options.AppKeys = "key1,key2,key3";
    options.AppKeyName = "appKey";
    options.TimeStampName = "timeStamp";
    options.ExpiresMinute = 2;
    options.SignKey = "your-sign-key";
    options.SignatureName = "signature";
    options.IgnoreApi = "/public/*,/health";
});

// 配置文件方式  
builder.Services.ApISignSetup(builder.Configuration.GetSection("AopOption:AppSign"));
配置文件
{
  "AppSign": {
    "AppKeys": "key1,key2,key3",
    "AppKeyName": "appKey", 
    "TimeStampName": "timeStamp",
    "ExpiresMinute": 2,
    "SignKey": "your-sign-key",
    "SignatureName": "signature",
    "IgnoreApi": "/public/*,/health"
  }
}

7. 前端 UI 文件处理

// 将前端 UI 压缩文件进行解压
builder.Services.AddUiFilesZipSetup();

// 使用虚拟路径中间件
app.UseVirtualPathMiddle();
虚拟路径配置
{
  "VirtualPath": "/myapp"
}

🔧 核心接口和类

1. IRestfulFilterLog 接口

public interface IRestfulFilterLog
{
    // 成功返回值处理
    IActionResult OnSucceeded(ActionExecutedContext context, object data);
    
    // 验证失败返回值处理  
    IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata);
    
    // 异常日志记录
    void ExceptionLog(ExceptionVo exception);
    
    // 操作日志记录
    void OperationLog(OperationVo operation);
}

2. 预实现类 RestfulFilterLog

public class RestfulFilterLog : IRestfulFilterLog
{
    // 操作日志记录(可重写)
    public virtual void OperationLog(OperationVo operation)
    {
        // 默认实现
    }
    
    // 异常日志记录(可重写)  
    public virtual void ExceptionLog(ExceptionVo exception)
    {
        // 默认实现
    }
}

3. 数据模型

ExceptionVo - 异常信息
public class ExceptionVo
{
    public string RequestUrl { get; set; }
    public string RequestMethod { get; set; }
    public string UserAgent { get; set; }
    public string IPAddress { get; set; }
    public DateTime OccurredTime { get; set; }
    public string ExceptionType { get; set; }
    public string ExceptionMessage { get; set; }
    public string StackTrace { get; set; }
    public string InnerException { get; set; }
}
OperationVo - 操作日志
public class OperationVo
{
    public string RequestUrl { get; set; }
    public string RequestMethod { get; set; }
    public string UserAgent { get; set; }
    public string IPAddress { get; set; }
    public DateTime RequestTime { get; set; }
    public long ExecutionTime { get; set; }
    public string Parameters { get; set; }
    public string Response { get; set; }
    public int StatusCode { get; set; }
    public string UserId { get; set; }
    public string UserName { get; set; }
}

🚀 完整使用示例

1. 自定义日志处理器

public class CustomRestfulFilterLog : RestfulFilterLog
{
    private readonly ILogger<CustomRestfulFilterLog> _logger;
    private readonly IOperationLogService _operationLogService;
    
    public CustomRestfulFilterLog(ILogger<CustomRestfulFilterLog> logger, 
                                 IOperationLogService operationLogService)
    {
        _logger = logger;
        _operationLogService = operationLogService;
    }
    
    // 重写操作日志记录方法
    public override void OperationLog(OperationVo operation)
    {
        // 记录到日志系统
        _logger.LogInformation("操作日志: {Url} {Method} {StatusCode} {ExecutionTime}ms", 
            operation.RequestUrl, operation.RequestMethod, operation.StatusCode, operation.ExecutionTime);
        
        // 保存到数据库
        _operationLogService.SaveAsync(new OperationLogEntity
        {
            Url = operation.RequestUrl,
            Method = operation.RequestMethod,
            UserId = operation.UserId,
            UserName = operation.UserName,
            IpAddress = operation.IPAddress,
            UserAgent = operation.UserAgent,
            Parameters = operation.Parameters,
            Response = operation.Response,
            StatusCode = operation.StatusCode,
            ExecutionTime = operation.ExecutionTime,
            RequestTime = operation.RequestTime
        });
    }
    
    // 重写异常日志记录方法
    public override void ExceptionLog(ExceptionVo exception)
    {
        // 记录异常到日志系统
        _logger.LogError(exception.Exception, 
            "异常信息: {Url} {Method} {ExceptionType}", 
            exception.RequestUrl, exception.RequestMethod, exception.ExceptionType);
        
        // 发送异常通知
        SendExceptionNotification(exception);
    }
    
    private void SendExceptionNotification(ExceptionVo exception)
    {
        // 发送邮件、短信、钉钉等通知
        // 实现异常告警逻辑
    }
}

2. 自定义注册

// 注册自定义的过滤器日志处理器
builder.Services.AddRestfulSetup<CustomRestfulFilterLog>();

3. 控制器使用示例

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    [HttpGet("profile")]
    public IActionResult GetUserProfile()
    {
        // 自动记录操作日志和异常
        var user = new { Id = 1, Name = "张三", Email = "zhangsan@example.com" };
        return Ok(user);
    }
    
    [HttpPost("update")]
    [NonAplSign] // 不进行签名验证
    public IActionResult UpdateUser([FromBody] UserUpdateDto dto)
    {
        // 自动参数验证
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        // 业务逻辑...
        return Ok(new { Success = true, Message = "更新成功" });
    }
    
    [HttpGet("sensitive-data")]
    [NonResource] // 不对资源进行过滤
    public IActionResult GetSensitiveData()
    {
        // 返回敏感数据,不进行资源过滤
        return Ok(new { Data = "敏感信息" });
    }
    
    [HttpPost("batch-operation")]
    [NonException] // 不进行异常日志收集
    public IActionResult BatchOperation()
    {
        // 批量操作,不记录异常日志
        try 
        {
            // 业务逻辑...
            return Ok();
        }
        catch 
        {
            // 异常不会被全局异常过滤器捕获
            return StatusCode(500);
        }
    }
}

4. API 安全签名验证

前端签名生成
// 前端签名生成示例
function generateSignature(appKey, signKey, data) {
    const timeStamp = Math.floor(Date.now() / 1000) + 1000; // 当前时间戳+1000秒
    const signContent = appKey + signKey + timeStamp + JSON.stringify(data);
    return md5(signContent); // 使用 MD5 加密
}

// 请求头设置
const headers = {
    'appKey': 'your-app-key',
    'timeStamp': timeStamp,
    'signature': generateSignature('your-app-key', 'your-sign-key', requestData)
};
后端签名验证
public class SignatureService
{
    public bool VerifySignature(string appKey, string timeStamp, string data, string signature, string signKey)
    {
        // 验证时间戳有效期
        if (!IsTimestampValid(timeStamp, 2)) // 2分钟有效期
        {
            return false;
        }
        
        // 验证 appKey 有效性
        if (!IsAppKeyValid(appKey))
        {
            return false;
        }
        
        // 生成期望的签名
        string expectedSignature = GenerateMD5(appKey + signKey + timeStamp + data);
        
        // 比较签名
        return signature == expectedSignature;
    }
    
    private bool IsTimestampValid(string timestamp, int expiresMinute)
    {
        if (!long.TryParse(timestamp, out long ts))
            return false;
            
        var requestTime = DateTimeOffset.FromUnixTimeSeconds(ts).DateTime;
        var now = DateTime.Now;
        
        return now <= requestTime && requestTime <= now.AddMinutes(expiresMinute);
    }
    
    private bool IsAppKeyValid(string appKey)
    {
        var validAppKeys = new[] { "key1", "key2", "key3" };
        return validAppKeys.Contains(appKey);
    }
    
    private string GenerateMD5(string input)
    {
        using var md5 = MD5.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(input);
        byte[] hashBytes = md5.ComputeHash(inputBytes);
        return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
    }
}

5. HTTP 上下文扩展使用

public class RequestInfoService
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    
    public RequestInfoService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    
    public RequestInfo GetRequestInfo()
    {
        var context = _httpContextAccessor.HttpContext;
        
        return new RequestInfo
        {
            Url = context.Request.GetRequestUrlAddress(),
            Host = context.Request.GetRequestHost(),
            Browser = context.GetBrowser(),
            OS = context.GetOSVersion(),
            IP = context.GetIp(),
            UserAgent = context.UserAgent(),
            ClientInfo = context.GetDefault()
        };
    }
    
    public void SigninToSwagger(string token)
    {
        _httpContextAccessor.HttpContext.SigninToSwagger(token);
    }
    
    public void SignoutFromSwagger()
    {
        _httpContextAccessor.HttpContext.SignoutToSwagger();
    }
}

public class RequestInfo
{
    public string Url { get; set; }
    public string Host { get; set; }
    public string Browser { get; set; }
    public string OS { get; set; }
    public string IP { get; set; }
    public string UserAgent { get; set; }
    public ClientInfo ClientInfo { get; set; }
}

6. 整合配置示例

Program.cs 完整配置
var builder = WebApplication.CreateBuilder(args);

// 添加控制器
builder.Services.AddControllers();

// 配置过滤器
builder.Services.ExceptionSetup(builder.Configuration.GetSection("AopOption:ExceptionLog"));
builder.Services.RequestActionSetup(builder.Configuration.GetSection("AopOption:RequestLog"));
builder.Services.ResourceSetup();
builder.Services.ResultSetup();
builder.Services.ApISafeSetup(builder.Configuration.GetSection("AopOption:ApISafe"));
builder.Services.ApISignSetup(builder.Configuration.GetSection("AopOption:AppSign"));

// 注册自定义过滤器日志
builder.Services.AddRestfulSetup<CustomRestfulFilterLog>();

// 规范化模型验证
builder.Services.AddRestfulModelsSetup(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

// 前端 UI 文件处理
builder.Services.AddUiFilesZipSetup();

var app = builder.Build();

// 使用虚拟路径中间件
app.UseVirtualPathMiddle();

// 其他中间件...
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();
appsettings.json 完整配置
{
  "AopOption": {
    "RequestLog": {
      "Enabled": true,
      "LogToFile": false,
      "LogMore": true,
      "IgnoreApis": "/health,/metrics,/swagger"
    },
    "ExceptionLog": {
      "Enabled": true,
      "LogToFile": true,
      "LogMore": true
    },
    "ApISafe": {
      "AppKeys": "web-app,mobile-app,admin-app",
      "AppKeyName": "appKey",
      "TimeStampName": "timeStamp",
      "ExpiresMinute": 2
    },
    "AppSign": {
      "AppKeys": "web-app,mobile-app,admin-app",
      "AppKeyName": "appKey",
      "TimeStampName": "timeStamp",
      "ExpiresMinute": 2,
      "SignKey": "your-secret-sign-key-2024",
      "SignatureName": "signature",
      "IgnoreApi": "/public/*,/health,/swagger"
    }
  },
  "VirtualPath": "/myapp"
}

🎯 特性排除

Non 特性列表

  • [NonAplSafe] - 不进行接口安全校验
  • [NonAplSign] - 不进行签名验证
  • [NonException] - 不进行全局异常日志收集
  • [NonResource] - 不对资源型信息进行过滤
  • [NonRestfulResult] - 不对结果进行统一

🔧 设计优势

  1. 模块化设计:各功能可独立启用或禁用
  2. 灵活配置:支持代码配置和配置文件配置
  3. 易于扩展:接口设计支持自定义实现
  4. 性能优化:支持忽略特定 API
  5. 安全可靠:完整的 API 安全校验机制
  6. 多语言支持:支持简体中文、繁体中文、粤语、日语、法语、英语

这个过滤器组件为 ASP.NET Core 应用提供了企业级的全局处理能力,大幅提升了应用的稳定性、安全性和可维护性。

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (12)

Showing the top 5 NuGet packages that depend on RuoVea.ExFilter:

Package Downloads
RuoVea.OmiDict

字典管理

RuoVea.OmiApi.UserRoleMenu

用户角色菜单管理

RuoVea.OmiConfig

参数配置

RuoVea.OmiApi.SystemApp

系统应用管理

RuoVea.OmiApi.UserRole

用户角色管理

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0.3 131 1/27/2026
10.0.0.2 83 1/26/2026
9.0.0.4 160 1/27/2026
9.0.0.3 88 1/26/2026
9.0.0.2 222 10/23/2025
8.0.1.9 425 1/27/2026
8.0.1.8 88 1/26/2026
8.0.1.7 2,787 10/23/2025
8.0.1.6 1,013 9/16/2025
7.0.1.9 470 1/27/2026
7.0.1.8 83 1/26/2026
7.0.1.7 3,278 10/23/2025
7.0.1.6 1,195 9/16/2025
6.0.19.9 578 1/27/2026
6.0.19.8 86 1/26/2026
6.0.19.7 4,009 10/23/2025
6.0.19.6 1,408 9/16/2025
5.0.0.8 89 1/27/2026
5.0.0.7 83 1/26/2026
5.0.0.6 208 10/23/2025
Loading failed