IGeekFan.FreeKit.Infrastructure
核心基础设施项目,提供 Controller 基类、DDD 约定、认证授权、缓存、异常通知等能力。
功能概览
| 功能 | 说明 |
|---|---|
| Controller 基类 | FreeKitController 统一基类 |
| 认证授权 | JWT / OpenIddict 认证、权限验证 |
| 缓存 | Redis / 内存缓存 |
| 异常体系 | BusinessException + 通知 |
| 过滤器 | 异常通知、数据脱敏 |
| 工具类 | AES/DES/SM4/MD5 加解密 |
Controller 基类
KitApiControllerBase
最底层基类,不需要认证:
[ApiController]
public abstract class KitApiControllerBase : ControllerBase
{
}
FreeKitController
带认证的基类,大多数控制器继承这个:
[Authorize]
public abstract class FreeKitController : KitApiControllerBase
{
}
使用示例
// 需要认证的 API
[ApiController]
[Route("api/[controller]")]
public class ArticleController : FreeKitController
{
private readonly IArticleService _articleService;
public ArticleController(IArticleService articleService)
{
_articleService = articleService;
}
[HttpGet]
public async Task<IActionResult> GetList()
{
var articles = await _articleService.GetListAsync();
return Ok(articles);
}
}
// 不需要认证的 API
[ApiController]
[Route("api/[controller]")]
public class PublicController : KitApiControllerBase
{
[HttpGet("health")]
public IActionResult Health() => Ok("ok");
}
应用服务基类
ApplicationService
提供常用服务的懒加载注入:
public class ArticleService : ApplicationService, IArticleService
{
private readonly IArticleRepository _repository;
public ArticleService(IArticleRepository repository)
{
_repository = repository;
}
public async Task<List<ArticleDto>> GetListAsync()
{
// CurrentUser - 当前用户
// UnitOfWorkManager - 工作单元
// Mediator - MediatR 中介者
// CapPublisher - 分布式事件发布
// Logger - 日志
// AuthorizationService - 授权服务
// PermissionStore - 权限存储
var userId = CurrentUser.FindUserId();
var articles = await _repository.GetListAsync();
return articles.MapTo<List<ArticleDto>>();
}
}
ApplicationService 可用服务
| 属性 | 类型 | 说明 |
|---|---|---|
CurrentUser | ICurrentUser | 当前用户信息 |
UnitOfWorkManager | UnitOfWorkManager | 工作单元管理器 |
Mediator | IMediator | MediatR 中介者 |
CapPublisher | ICapPublisher | CAP 分布式事件发布 |
Logger | ILogger | 日志记录器 |
AuthorizationService | IAuthorizationService | 授权服务 |
PermissionStore | IPermissionStore | 权限存储 |
CrudAppService
CRUD 应用服务模板:
public class ArticleCrudService : CrudAppService<
Article, // 实体
ArticleDto, // 输出 DTO
ArticleListDto, // 列表 DTO
Guid, // 主键类型
PageQuery, // 查询参数
CreateArticleRequest, // 创建请求
UpdateArticleRequest // 更新请求
>, IArticleCrudService
{
public ArticleCrudService(IBaseRepository<Article, Guid> repository) : base(repository)
{
}
}
// 自动获得:GetListAsync / GetAsync / CreateAsync / UpdateAsync / DeleteAsync
CrudAppService 可重写方法
| 方法 | 说明 |
|---|---|
CreateFilteredQuery() | 自定义查询过滤器 |
ApplySorting() | 自定义排序逻辑 |
EntityListToDtoListAsync() | 自定义实体到 DTO 映射 |
GetEntityByIdAsync() | 获取实体并验证权限 |
ValidateEntityPermissions() | 验证实体权限 |
领域服务基类
DomainService
public class OrderDomainService : DomainService, IOrderDomainService
{
private readonly IOrderRepository _repository;
public OrderDomainService(IOrderRepository repository)
{
_repository = repository;
}
public async Task ProcessOrderAsync(Guid orderId)
{
// CurrentUser - 当前用户
// UnitOfWorkManager - 工作单元
// Logger - 日志
var order = await _repository.FindAsync(orderId);
// 业务逻辑...
}
}
DomainService 可用服务
| 属性 | 类型 | 说明 |
|---|---|---|
CurrentUser | ICurrentUser | 当前用户信息 |
UnitOfWorkManager | UnitOfWorkManager | 工作单元管理器 |
Logger | ILogger | 日志记录器 |
AuthorizationService | IAuthorizationService | 授权服务 |
CurrentUnitOfWork | IUnitOfWork | 当前工作单元 |
领域事件分发
public class OrderDomainService : DomainService, IOrderDomainService
{
private readonly IDomainEventDispatcher _eventDispatcher;
public async Task PlaceOrderAsync(Order order)
{
// 业务逻辑...
// 添加领域事件
order.AddDomainEvent(new OrderPlacedEvent(order.Id));
// 分发事件
await _eventDispatcher.DispatchAndClearEvents(new[] { order });
}
}
缓存系统
两种缓存策略
| 策略 | 说明 |
|---|---|
CacheStrategyType.Redis | 基于 FreeRedis |
CacheStrategyType.Memory | 基于 ConcurrentDictionary |
使用方式
// 1. 注册缓存服务
builder.Services.AddCacheStrategy(CacheStrategyType.Redis);
// 2. 在服务中使用
public class ArticleService : IScopedDependency
{
private readonly ICacheService _cache;
public ArticleService(ICacheService cache) => _cache = cache;
public async Task<Article> GetByIdAsync(Guid id)
{
// 带缓存壳的读取
return await _cache.CacheShell(
$"article:{id}",
async () => await _repository.FindAsync(id),
expireSeconds: 300
);
}
}
// 3. 或使用 AOP 缓存
[Cacheable(CacheKey = "article:{id}", ExpireSeconds = 300)]
public async Task<Article> GetByIdAsync(Guid id)
{
return await _repository.FindAsync(id);
}
Cacheable 特性
[Cacheable(
CacheKey = "user:{userId}", // 缓存键,支持 {参数名}
ExpireSeconds = 300, // 过期时间(秒)
CacheStrategy = CacheStrategyType.Redis // 缓存策略
)]
public async Task<UserDto> GetUserAsync(Guid userId) { ... }
异常体系
常用异常
// 业务异常
throw new BusinessException("订单状态不允许操作");
// 实体不存在
throw new EntityNotFoundException(typeof(Article), id);
// 请求异常
throw new BadRequestException("参数无效");
// 带 Guard 验证
Guard.NegativeOrZero(amount, nameof(amount));
Guard.Null(order, nameof(order));
Guard.NotFound(id, nameof(id));
异常类型
| 异常类 | 说明 |
|---|---|
BusinessException | 业务异常,带 Code 和 StatusCode |
EntityNotFoundException | 实体不存在 |
BadRequestException | 请求参数错误 |
InvalidEmailException | 无效邮箱格式 |
InvalidDateException | 无效日期 |
统一响应
// 成功
return Ok(ApiResponse.Ok(data));
// 失败
return BadRequest(ApiResponse.Failed("错误信息"));
// 业务异常
throw new BusinessException(ResponseCode.BusinessException, "业务错误");
ResponseCode 枚举
| 值 | 说明 |
|---|---|
Success(0) | 成功 |
BusinessException(1001) | 业务异常 |
Failed(1002) | 失败 |
AuthenticationFailed(10000) | 认证失败 |
NoPermission(10001) | 无权限 |
NotFound(10020) | 未找到 |
ParameterError(10030) | 参数错误 |
TokenExpired(10050) | Token 过期 |
ManyRequests(10140) | 请求过多 |
授权系统
权限验证
// 方式一:使用 Policy
[Authorize(Policy = "Article.Create")]
public IActionResult Create() { }
// 方式二:使用特性
[KitAuthorize("Article.Delete")]
public IActionResult Delete() { }
认证模式
public enum AuthMode
{
Jwt = 0, // JWT 自签发
OpenIddict = 1 // OpenIddict 验证
}
JWT 配置
{
"JwtSettings": {
"Issuer": "https://localhost:5001",
"Audience": "https://localhost:5001",
"SecretKey": "your-secret-key-min-32-chars",
"ExpireMinutes": 60
}
}
CookieJwtBearerHandler
支持三种 Token 来源:
- Query string (
?access_token=...) - SignalR Hub - Authorization header - 标准 JWT
- Cookie (
access_tokencookie)
实现权限存储
public class PermissionStore : IPermissionStore
{
public async Task<bool> CheckPermissionAsync(string permission)
{
// 检查用户是否有指定权限
}
public async Task<bool> CheckAccessTokenAsync(string accessToken)
{
// 检查 Token 是否有效
}
}
异常通知
支持三通道告警:邮件、飞书、企业微信。
{
"ExceptionNotify": {
"Enabled": true,
"Mail": {
"Enabled": true,
"MailTo": "ops@example.com"
},
"Feishu": {
"Enabled": true,
"WebhookUrl": "https://open.feishu.cn/..."
},
"WeCom": {
"Enabled": false
}
}
}
加密工具
AES 加密
var encrypted = AESUtil.Encrypt(plainText, key, iv);
var decrypted = AESUtil.Decrypt(encrypted, key, iv);
DES 加密
var encrypted = DESUtil.Encrypt(plainText, key, iv);
var decrypted = DESUtil.Decrypt(encrypted, key, iv);
SM4 国密
var key = SM4Util.GenerateKey();
var encrypted = SM4Util.Encrypt_CBC_Padding(key, iv, data);
var decrypted = SM4Util.Decrypt_CBC_Padding(key, iv, encrypted);
MD5 哈希
var hash32 = Md5Util.Md5(plainText, MD5Digit.Digit32);
var hash16 = Md5Util.Md5(plainText, MD5Digit.Digit16);
var verified = EncryptUtil.Verify(md5Hash, plainText);
Base64 编码
var encoded = ToolHelper.Base64Encode(content);
var decoded = ToolHelper.Base64Decode(encoded);
数据脱敏
var masked = MaskHelper.MaskPhoneNumber("13812345678");
// 结果: "138****5678"
中间件
加密中间件
// Program.cs
app.UseEncryption();
// 配置
{
"Encryption": {
"Enable": true,
"EncryptionKey": "your-key",
"EncryptionIV": "your-iv"
}
}
Basic 认证中间件
// 保护 Swagger
{
"Basic": {
"Enable": true,
"ProtectPaths": ["/swagger"],
"UserName": "admin",
"UserPassword": "123456"
}
}
IP 限流
// 注册限流服务
builder.Services.AddIpRateLimiting(builder.Configuration);
// 配置
{
"IpRateLimiting": {
"Enable": true,
"MaxRequestsPerSecond": 10,
"RetryAfterSeconds": 60
}
}
过滤器
SensitiveDataAttribute
数据脱敏过滤器:
public class UserDto
{
[SensitiveData]
public string Phone { get; set; } // 自动脱敏
[SensitiveData(Mask = "***")]
public string Email { get; set; }
}
RecaptchaVerifyActionFilter
Google reCAPTCHA 验证:
[ServiceFilter(typeof(RecaptchaVerifyActionFilter))]
[HttpPost]
public IActionResult Submit(SubmitRequest request)
{
// 自动验证 reCAPTCHA
}
安全工具
CurrentUserExtensions
// 获取用户 ID
var userId = CurrentUser.FindUserId();
// 检查是否管理员
if (CurrentUser.IsAdmin()) { ... }
// 检查是否模拟登录
if (CurrentUser.IsImpersonating()) { ... }
// 获取模拟者信息
var impersonatorId = CurrentUser.FindImpersonatorUserId();
DTO 基类
ApiResponse
// 成功响应
return Ok(ApiResponse.Ok(data));
// 失败响应
return BadRequest(ApiResponse.Failed("错误信息"));
// 带状态码
return Ok(ApiResponse.New(ResponseCode.Success, data));
PageQuery
分页查询基类:
public class ArticleListQuery : PageQuery
{
public string? Keyword { get; set; }
}
// 使用
[HttpGet]
public async Task<PagerListDto<ArticleDto>> GetList(ArticleListQuery query)
{
return await _articleService.GetListAsync(query);
}
ISortedResultRequest
排序支持:
// 通过逗号分隔排序
// 例如: "Name ASC, Age DESC"
public string? Sorting { get; set; }
扩展方法
分页扩展
// FreeSql 分页
var list = await _fsql.Select<Article>()
.ToPagerListAsync(query);
// 内存分页
var list = articles.ToPagerList(query);
文件扩展
// 递归获取文件
var files = fileProvider.GetFilesRecursively();
// 读取文件内容
var content = await fileInfo.ReadAsStringAsync();
CAP 扩展
// 开启事务
ICapTransaction tx = unitOfWork.BeginTransaction(publisher, autoCommit: false);
// 提交事务
tx.Commit(unitOfWork);