RuoVea.ExFilter 9.0.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package RuoVea.ExFilter --version 9.0.0.2
                    
NuGet\Install-Package RuoVea.ExFilter -Version 9.0.0.2
                    
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="9.0.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RuoVea.ExFilter" Version="9.0.0.2" />
                    
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 9.0.0.2
                    
#r "nuget: RuoVea.ExFilter, 9.0.0.2"
                    
#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@9.0.0.2
                    
#: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=9.0.0.2
                    
Install as a Cake Addin
#tool nuget:?package=RuoVea.ExFilter&version=9.0.0.2
                    
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 net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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.OmiApi.UserRoleMenu

用户、角色、菜单管理 API

RuoVea.OmiApi.UserRole

用户角色管理 API

RuoVea.OmiDict

字典管理

RuoVea.OmiConfig

参数配置

RuoVea.OmiApi.User

用户管理 API

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0.1 308 9/16/2025
9.0.0.2 154 10/23/2025
9.0.0 484 7/25/2025
8.0.1.7 344 10/23/2025
8.0.1.6 925 9/16/2025
8.0.1.5 1,965 4/23/2025
8.0.1.4 1,235 11/21/2024
8.0.1.3 203 11/1/2024
8.0.1.2 175 9/22/2024
8.0.1.1 194 9/18/2024
8.0.1 181 8/28/2024
8.0.0 159 7/23/2024
7.0.1.7 361 10/23/2025
7.0.1.6 1,099 9/16/2025
7.0.1.5 2,261 4/23/2025
7.0.1.4 1,426 11/21/2024
7.0.1.3 169 11/1/2024
7.0.1.2 185 9/22/2024
7.0.1.1 178 9/18/2024
7.0.1 171 8/28/2024
7.0.0 158 7/23/2024
6.0.19.7 426 10/23/2025
6.0.19.6 1,292 9/16/2025
6.0.19.5 2,729 4/23/2025
6.0.19.4 4,302 11/21/2024
6.0.19.3 1,612 11/1/2024
6.0.19.2 1,999 9/22/2024
6.0.19.1 206 9/18/2024
6.0.19 175 8/28/2024
6.0.18.13 231 8/25/2024
6.0.18.12 224 4/15/2024
6.0.18.11 215 4/14/2024
6.0.18.10 239 3/13/2024
6.0.18.9 256 3/13/2024
6.0.18.8 245 3/11/2024
6.0.18.7 300 2/28/2024
6.0.18.6 260 2/27/2024
6.0.18.5 334 1/29/2024
6.0.18.4 336 1/27/2024
6.0.18.3 302 1/26/2024
6.0.18.2 423 12/28/2023
6.0.18.1 356 12/1/2023
6.0.18 384 9/27/2023
6.0.17 370 9/16/2023
6.0.16 520 3/26/2023
6.0.15 510 3/26/2023
6.0.13 530 3/11/2023
6.0.12 583 12/23/2022
6.0.11 520 12/23/2022
6.0.10 663 10/8/2022
6.0.9 730 9/16/2022
6.0.8 706 8/18/2022
6.0.7 723 6/10/2022
6.0.6 780 3/15/2022
6.0.5 763 3/14/2022
6.0.4 747 2/18/2022
6.0.3 691 2/18/2022
6.0.2 737 2/17/2022
6.0.1 767 2/15/2022
6.0.0 774 2/11/2022
5.0.0.6 143 10/23/2025
5.0.0.5 308 9/16/2025
5.0.0.4 216 4/23/2025
5.0.0.3 183 11/21/2024
5.0.0.2 193 11/1/2024
5.0.0.1 176 9/22/2024
5.0.0 178 9/18/2024