RuoVea.OmiApi.UserRole 10.0.1.8

dotnet add package RuoVea.OmiApi.UserRole --version 10.0.1.8
                    
NuGet\Install-Package RuoVea.OmiApi.UserRole -Version 10.0.1.8
                    
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.OmiApi.UserRole" Version="10.0.1.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RuoVea.OmiApi.UserRole" Version="10.0.1.8" />
                    
Directory.Packages.props
<PackageReference Include="RuoVea.OmiApi.UserRole" />
                    
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.OmiApi.UserRole --version 10.0.1.8
                    
#r "nuget: RuoVea.OmiApi.UserRole, 10.0.1.8"
                    
#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.OmiApi.UserRole@10.0.1.8
                    
#: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.OmiApi.UserRole&version=10.0.1.8
                    
Install as a Cake Addin
#tool nuget:?package=RuoVea.OmiApi.UserRole&version=10.0.1.8
                    
Install as a Cake Tool

RuoVea.OmiApi.UserRole

用户角色管理 API 组件 —— 提供用户、角色、用户角色关联的完整 CRUD 服务。

RuoVea.OmiApi.UserRole 是一个开箱即用的用户角色管理系统 NuGet 包,包含系统用户管理(增删改查、密码管理、状态控制、角色授权、登录锁定解除)、系统角色管理(增删改查、状态控制、权限数据隔离)和缓存服务。支持多租户(ITenantEntity)、种子数据初始化、JWT 认证、密码加密/强度校验和数据库表自动迁移。基于 SqlSugar ORMDynamicWebApi,注册即自动生成 RESTful API 端点,支持 MySql / SqlServer / PostgreSQL / SQLite / Oracle 等多种数据库。

⚠️ 互斥「基座」组件:本组件与 RuoVea.OmiApi.User(仅用户)、RuoVea.OmiApi.UserRoleMenu(用户+角色+菜单+租户)为互斥的基座组件,功能逐级增强,只能按需选择其一安装,不可同时引用


目录


概览

功能特性

模块 功能
👤 用户管理 增删改查、分页查询、密码修改与重置、登录锁定解除、状态启停、角色授权
🛡️ 角色管理 增删改查、分页查询(含权限过滤)、状态设置、级联删除检查
🔗 用户角色关联管理 批量授权用户角色、批量授权角色用户、按用户Id或角色Id删除关联
💾 缓存服务 Set/Get/Remove 缓存操作、前缀批量删除、缓存存在性检查、异步缓存代理
🏢 多租户支持 SysRole 和 SysUser 实现 ITenantEntity 接口,支持租户数据隔离
🌱 种子数据 预置超级管理员(superAdmin)、系统管理员(admin)、普通用户(ruovea)及对应角色
🗄️ 多库支持 MySql、SqlServer、PostgreSQL、SQLite、Oracle、Dm 等
🧩 自动 API 实现 IApplicationService 即自动映射为 REST 控制器
🔐 密码安全 用户密码使用 IPasswordServer 加密存储,支持密码强度校验与已加密/明文双输入(isEncPass
🌐 i18n 国际化 通过 .resx 资源文件提供中文本地化错误/提示信息

架构一览

┌──────────────────────────────────────────────────────────────────────┐
│                        NuGet Package                                  │
│  RuoVea.OmiApi.UserRole                                               │
├──────────────────────────────────────────────────────────────────────┤
│  Service Layer (4 Services)                                           │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐   │
│  │  SysUserService  │  │  SysRoleService  │  │SysUserRoleService│   │
│  │  · GetPagesAsync │  │  · GetPagesAsync │  │  (内部服务)       │   │
│  │  · AddUser       │  │  · AddRole       │  │  · GetUserRoles  │   │
│  │  · UpdateUser    │  │  · UpdateRole    │  │  · GetRoleUsers  │   │
│  │  · DeleteUser    │  │  · DeleteRole    │  │  · GrantRoles    │   │
│  │  · ChangePwd     │  │  · SetStatus     │  │  · RemoveByUserId│   │
│  │  · ResetPwd      │  │                  │  └──────────────────┘   │
│  │  · GrantRole     │  └──────────────────┘                          │
│  │  · UnlockLogin   │                                                │
│  │  · SetStatus     │  ┌──────────────────┐                          │
│  └──────────────────┘  │ SysCacheService  │                          │
│                         │  · Set/Get/Remove │                          │
│                         │  · RemoveByPrefix │                          │
│                         │  · Clear         │                          │
│                         └──────────────────┘                          │
├──────────────────────────────────────────────────────────────────────┤
│  Domain Layer (3 Entities)                                            │
│  ┌─────────────────────┐                                             │
│  │  SysUser            │────< SysUserRole >───┐                      │
│  │  · Account/Password │                      │                      │
│  │  · NickName/Phone   │                  ┌─────────────┐            │
│  │  · IsDisable/Status │                  │  SysRole    │            │
│  │  · TenantId (多租户) │                  │  · Name/Code│            │
│  └─────────────────────┘                  │  · Sort     │            │
│                                           │  · IsDisable│            │
│                                           │  · TenantId │            │
│                                           └─────────────┘            │
├──────────────────────────────────────────────────────────────────────┤
│  Infrastructure                                                       │
│  SqlSugar ORM  ·  DynamicWebApi  ·  ExSugar Repo  ·  JWT Bearer      │
│  ExFilter (异常拦截)  ·  ExPws (密码加密)  ·  ExJwtBearer (认证)      │
└──────────────────────────────────────────────────────────────────────┘

领域模型 ER 关系

  SysUser (1) ────< SysUserRole >──── (1) SysRole
  ┌────────┐       ┌───────────┐       ┌───────┐
  │ Id     │───┐   │ Id        │   ┌───│ Id    │
  │ Account│   ├──>│ UserId    │   │   │ Name  │
  │ ...    │   │   │ RoleId    │<──┘   │ Code  │
  │TenantId│   │   │ SysUser   │       │TenantId│
  └────────┘   │   │ SysRole   │       └───────┘
               │   └───────────┘
               │   SysUserRole 是多对多中间表
               │   含 SysUser 和 SysRole 导航属性 (OneToOne)
               └── UserId = SysUser.Id (FK)
               RoleId = SysRole.Id (FK)

支持的 .NET 版本

TFM NuGet 版本
net8.0 8.0.3.8
net10.0 10.0.1.6

安装

NuGet 包管理器

# .NET 8 项目
Install-Package RuoVea.OmiApi.UserRole -Version 8.0.3.8

# .NET 10 项目
Install-Package RuoVea.OmiApi.UserRole -Version 10.0.1.6

.NET CLI

dotnet add package RuoVea.OmiApi.UserRole --version 8.0.3.8

依赖项

本包依赖以下组件(安装时会自动引入):

包名 用途
RuoVea.ExFilter 全局异常拦截与模型验证
RuoVea.ExJwtBearer JWT Bearer 认证配置
RuoVea.ExPws 密码加密与强度校验(IPasswordServer)
RuoVea.OmiApi.Config 系统配置管理(DbInitConfig、Swagger等)
RuoVea.DynamicWebApi 动态 API 控制器生成
RuoVea.ExSugar SqlSugar 仓储模式封装

30 秒快速开始

1. 配置数据库连接 (appsettings.json)

{
  "ConnectionConfigs": [
    {
      "DbType": "Sqlite",
      "ConnectionString": "DataSource=./ruovea.db"
    }
  ],
  "Jwt": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "3c1cbc3f546eda35168c3aa3cb91780fbe703f0996c6d123ea96dc85c70bbc0a",
    "ValidateIssuer": true,
    "ValidIssuer": "SecurityDemo.Authentication.JWT",
    "ValidateAudience": true,
    "ValidAudience": "jwtAudience",
    "ValidateLifetime": true,
    "ExpiredTime": 1440,
    "ClockSkew": 5
  },
  "PasswordConfig": {
    "DefaultPassword": "123456",
    "StrongPassword": true
  },
  "DbInitConfig": {
    "InitTable": true,
    "InitSeedData": true
  },
  "Swagger": {
    "ApiVersions": [
      {
        "Title": "用户角色管理",
        "Version": "system"
      }
    ]
  }
}

支持的 DbType 值: MySqlSqlServerSqliteOraclePostgreSQLDmKdbndpOpenGaussClickHouse 等。

2. 注册服务 (Program.cs)

// <summary>
// 在 Program.cs 中注册 OmiApi.UserRole 组件服务
// </summary>
var builder = WebApplication.CreateBuilder(args);

// 注册动态 Web API(自动将 Service 映射为 REST 控制器)
builder.Services.AddDynamicWebApi(options =>
{
    options.RemoveControllerPostfixes = new List<string> { "AppService", "Service" };
    options.RemovePrefix = new List<string> { "get", "post" };
});

// 注册 HttpContext 用户身份
builder.Services.AddHttpContextSetup<AspNetUser>();

// 注册 JWT 认证
builder.Services.AddAuthenticationSetup(IdentifyEnum.Jwt, true);

// 注册 SqlSugar ORM
builder.Services.AddSqlSugarSetup();

// 注册 UserRole 模块服务(默认 Scoped 生命周期)
builder.Services.AddOmiSystemSetup();

// 注册请求日志拦截、统一返回、异常处理
builder.Services
    .RequestActionSetup()
    .ResultSetup()
    .ExceptionSetup();

// 注册 Swagger
builder.Services.AddSwaggerSetup();

// 初始化数据库表结构和种子数据
builder.Services.AddSystemInitSetup();

// 跨域配置
builder.Services.AddCors(option =>
{
    option.AddDefaultPolicy(builder =>
    {
        builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
    });
});

var app = builder.Build();

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.Run();

3. 启动并访问 Swagger

启动项目后,访问 https://localhost:xxxx/swagger,即可看到 "用户角色管理" 分组下的全部 RESTful API 端点。


核心场景

场景一:创建用户并授权角色

// <summary>
// 创建新用户 —— 异步写法。创建成功后,为用户批量授权角色。
// </summary>
public async Task<bool> CreateUserWithRolesAsync(SysUserService userService)
{
    // Step 1: 创建用户
    var userInput = new AddUserInput
    {
        Account  = "zhangsan",
        Password = "P@ssw0rd!2024",
        NickName = "张三",
        RealName = "张三丰",
        Phone    = "13800138000",
        Email    = "zhangsan@example.com",
        Sex      = Gender.MALE,
        IsDisable = YesOrNot.N,
        Remark   = "市场部新员工"
    };

    var userId = await userService.AddUser(userInput);
    if (userId <= 0)
    {
        return false;
    }

    // Step 2: 为用户授权角色
    await userService.GrantRole(new UserRolesInput
    {
        UserId     = userId,
        RoleIdList = new List<long> { 2, 3 } // 授权角色 ID 列表
    });

    return true;
}

// <summary>
// 创建新用户 —— 同步写法。⚠️ 仅推荐在 Console/测试环境使用。
// </summary>
public bool CreateUserWithRoles(SysUserService userService)
{
    var userInput = new AddUserInput
    {
        Account  = "zhangsan",
        Password = "P@ssw0rd!2024",
        NickName = "张三",
        Phone    = "13800138000"
    };

    var userId = userService.AddUser(userInput).GetAwaiter().GetResult();
    if (userId <= 0) return false;

    userService.GrantRole(new UserRolesInput
    {
        UserId     = userId,
        RoleIdList = new List<long> { 2, 3 }
    }).GetAwaiter().GetResult();

    return true;
}
创建用户 + 授权角色流程:

  Step 1: 创建用户
    ├─ 校验 Account 唯一性(account_exists 检查)
    ├─ IPasswordServer 加密密码(空密码时使用默认密码)
    └─ INSERT SysUser

  Step 2: 授权用户角色
    ├─ 批量 INSERT SysUserRole (UserId, RoleId)
    └─ 清除该用户的按钮权限缓存(sys_user_button:{userId})

场景二:修改密码与重置密码

// <summary>
// 用户自主修改密码 —— 需验证旧密码。
// </summary>
public async Task<int> ChangeMyPasswordAsync(SysUserService userService)
{
    var input = new ChangePwdInput
    {
        PasswordOld = "OldP@ssw0rd",
        PasswordNew = "NewP@ssw0rd!2024",
        isEncPass   = false // 密码是否已加密,false 表示传入明文
    };

    // 内部校验:
    // 1. 旧密码是否正确 (password_error)
    // 2. 新旧密码不能相同 (new_password_same_as_old)
    // 3. 新密码强度校验(PasswordConfig.StrongPassword=true 时通过 IPasswordServer.Validate 校验)
    // 4. 新密码加密后 UPDATE SysUser.Password
    return await userService.ChangePwd(input);
}

// <summary>
// 管理员重置用户密码 —— 无需旧密码,重置为系统默认密码(PasswordConfig.DefaultPassword)。
// </summary>
public async Task<string> ResetUserPasswordAsync(SysUserService userService)
{
    var input = new ResetPwdUserInput
    {
        Id = 1001 // 仅需用户 Id,新密码为系统默认密码
    };

    // 内部操作:
    // 1. 检查用户是否存在 (account_not_exists)
    // 2. 密码重置为默认密码并加密(IPasswordServer.Encrypt)
    // 3. UPDATE SysUser SET Password = 加密后的默认密码
    // 4. 清空该用户的密码错误次数缓存
    return await userService.ResetPwd(input);
}
密码修改流程 (ChangePwd):

  开始
    │
    ├─ 1. 根据 JWT Token 获取当前登录用户
    │     若未登录 → 抛出认证异常
    │
    ├─ 2. 校验旧密码:isEncPass=false 时 Encrypt(旧密码) 与库中密码比对
    │     匹配失败 → 抛出 password_error
    │
    ├─ 3. 新密码 == 旧密码?
    │     是 → 抛出 new_password_same_as_old
    │
    ├─ 4. StrongPassword=true 时 IPasswordServer.Validate(新密码)
    │     不满足强度要求 → 抛出校验失败
    │
    └─ 5. UPDATE SysUser SET Password = IPasswordServer.Encrypt(新密码)
    │
  结束

场景三:用户状态管理与登录解锁

// <summary>
// 设置用户启用/停用状态 —— 含安全保护检查。
// </summary>
public async Task<int> ToggleUserStatusAsync(SysUserService userService, long userId, bool disable)
{
    var input = new UserInput
    {
        Id        = userId,
        IsDisable = disable ? YesOrNot.Y : YesOrNot.N
    };

    // ⚠️ 安全检查:
    // 1. prohibit_modify_self_status - 禁止修改本人账号状态
    // 2. prohibit_modify_super_admin_status - 禁止修改超级管理员状态
    // 3. 检查用户是否存在 (account_not_exists)
    // 4. 禁用时写黑名单缓存,启用时移除黑名单
    return await userService.SetStatus(input);
}

// <summary>
// 解除用户登录锁定 —— 清空该用户的密码错误次数缓存。
// </summary>
public async Task UnlockUserAsync(SysUserService userService, long userId)
{
    var input = new UnlockLoginInput
    {
        Id = userId
    };

    // 内部操作:
    // 1. 校验用户是否存在(account_not_exists)
    // 2. 删除密码错误次数缓存(sys_password_error_times:{Account})
    await userService.UnlockLogin(input);
}

场景四:角色管理与权限数据隔离

// <summary>
// 创建角色 —— 数据权限自动隔离。
// 内部自动设置 Creator 为当前登录用户。
// </summary>
public async Task CreateRoleAsync(SysRoleService roleService)
{
    var input = new AddRoleInput
    {
        Name      = "内容编辑",
        Code      = "content_editor",
        Sort      = 100,
        Remark    = "负责内容的审核与发布",
        IsDisable = YesOrNot.N
    };

    await roleService.AddRole(input);
}

// <summary>
// 分页查询角色 —— 非超管/系统管理员只能看到自己创建或已拥有的角色。
// </summary>
public async Task<PageResult<SysRole>> SearchRolesAsync(SysRoleService roleService)
{
    var param = new PageRoleInput
    {
        PageNo   = 1,
        PageSize = 10,
        Name     = "管理",          // 角色名称模糊搜索
        Code     = ""              // 角色编码模糊搜索
    };

    // 权限数据隔离逻辑(内部):
    // - 超级管理员 / 租户管理员 (IsTenantAdmin) → 查看所有角色
    // - 普通用户 → 仅查看自己创建的或已拥有的角色
    return await roleService.GetPagesAsync(param);
}

// <summary>
// 删除角色 —— 级联检查。
// </summary>
public async Task DeleteRoleAsync(SysRoleService roleService, long roleId)
{
    var input = new DeleteRoleInput { Id = roleId };

    // ⚠️ 安全检查:
    // 1. prohibit_delete_admin - 禁止删除系统管理员角色
    // 2. role_has_accounts     - 角色下存在关联用户时禁止删除
    // 3. record_not_exists     - 角色不存在

    await roleService.DeleteRole(input);
}
角色删除检查流程:

  DELETE 请求
    │
    ├─ 角色是否存在?
    │   否 → 抛出 record_not_exists
    │
    ├─ 是否为系统管理员角色?
    │   是 → 抛出 prohibit_delete_admin
    │
    ├─ 是否有用户关联该角色?
    │   SELECT COUNT(*) FROM SysUserRole WHERE RoleId = @id
    │   有 → 抛出 role_has_accounts
    │
    └─ DELETE SysRole WHERE Id = @id

场景五:缓存服务操作

// <summary>
// 缓存读写操作 —— 异步写法(仅异步接口可 await)。
// </summary>
public async Task CacheOperationsAsync(SysCacheService cacheService)
{
    // 设置缓存(带过期时间)—— [NonAction] 内部方法,同步返回 bool
    cacheService.Set("user:info:1001", new { Name = "张三", Role = "编辑" }, TimeSpan.FromMinutes(30));

    // 获取缓存值(同步返回 object)
    var cached = cacheService.GetValue("user:info:1001");

    // 检查缓存是否存在 —— [NonAction] 内部方法
    bool exists = cacheService.ExistKey("user:info:1001");

    // 获取指定前缀的键名集合(同步返回 List<string>)
    var keys = cacheService.GetKeysByPrefixKey("user:info:");

    // 批量删除指定前缀的缓存(异步)
    await cacheService.RemoveByPrefixKey("user:info:");

    // 清除单个缓存(同步返回 long)
    cacheService.Remove("user:info:1001");

    // 清空所有缓存(异步)
    await cacheService.Clear();
}

// <summary>
// 缓存操作 —— 同步写法。
// ⚠️ 注意:在 ASP.NET 上下文中可能导致死锁,仅推荐在 Console/测试环境使用。
// </summary>
public void CacheOperations(SysCacheService cacheService)
{
    cacheService.Set("key", "value", TimeSpan.FromMinutes(10)); // Set 返回 bool
    var value = cacheService.GetValue("key");                   // GetValue 返回 object
    cacheService.Remove("key");                                 // Remove 返回 long
}

配置选项详解

数据库连接配置 (ConnectionConfigs)

{
  "ConnectionConfigs": [
    {
      "DbType": "Sqlite",
      "ConnectionString": "DataSource=./ruovea.db",

      "EnableUnderLine": false,
      "EnableDiffLog": false,
      "IsEncrypt": false,
      "DbSecurity": "",
      "IsDeleteFilter": true,
      "IsUserIdFilter": false,
      "IsTenantIdFilter": false,
      "CommandTimeOut": 30
    }
  ]
}
参数 类型 默认值 说明
DbType string 必填 数据库类型
ConnectionString string 必填 连接字符串
EnableUnderLine bool false 驼峰转下划线
EnableDiffLog bool false 启用库表差异日志
IsEncrypt bool false 连接字符串是否加密
DbSecurity string "" 解密密钥(IsEncrypt=true 时使用)
IsDeleteFilter bool true ⚠️ 全局软删除过滤(实体需继承 IDeletedEntity
IsUserIdFilter bool false 按创建者过滤(实体需继承 ICreatorFilterEntityBase
IsTenantIdFilter bool false 按租户过滤(SysUser/SysRole 实现 ITenantEntity
CommandTimeOut int 30 SQL 命令超时时间(秒)

表初始化配置 (DbInitConfig)

{
  "DbInitConfig": {
    "InitTable": true,
    "InitSeedData": true
  }
}
参数 类型 默认值 说明
InitTable bool true 启动时自动检查并创建缺失的数据表(CodeFirst,含 SysRole / SysUser / SysUserRole)
InitSeedData bool true 是否写入种子数据(角色、超级管理员/系统管理员/普通用户及用户角色关联)

性能提醒: AddSystemInitSetup 在后台执行表检查和种子数据写入。生产环境首次启动后建议将 InitTableInitSeedData 设为 false,避免每次启动都执行 IsAnyTable 检查。

JWT 认证配置 (Jwt)

{
  "Jwt": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "your-secret-key-at-least-16-chars",
    "ValidateIssuer": true,
    "ValidIssuer": "SecurityDemo.Authentication.JWT",
    "ValidateAudience": true,
    "ValidAudience": "jwtAudience",
    "ValidateLifetime": true,
    "ExpiredTime": 1440,
    "ClockSkew": 5
  }
}
参数 类型 默认值 说明
ValidateIssuerSigningKey bool true 是否验证密钥
IssuerSigningKey string 必填 ⚠️ 签名密钥,长度须大于16字符
ValidateIssuer bool true 是否验证签发方
ValidIssuer string 签发方标识
ValidateAudience bool true 是否验证签收方
ValidAudience string 签收方标识
ValidateLifetime bool true 是否验证过期时间
ExpiredTime long 1440 Token 过期时间(分钟),默认 24 小时
ClockSkew long 5 过期时间容错值(秒)

密码配置 (PasswordConfig)

{
  "PasswordConfig": {
    "DefaultPassword": "123456",
    "StrongPassword": true
  }
}
参数 类型 默认值 说明
DefaultPassword string "123456" 新增/重置用户时的默认密码(加密后入库)
StrongPassword bool true 是否启用强密码校验(修改密码时通过 IPasswordServer.Validate() 校验强度)

⚠️ 安全提醒: 密码始终使用 IPasswordServer 加密存储,不存在明文入库模式。上生产环境前务必修改 DefaultPassword

DI 注册配置

// <summary>
// AddOmiSystemSetup —— 三种重载,适应不同配置来源。
// 注册服务: JWT、密码配置、SysCacheService、SysRoleService、SysUserRoleService、
//          SysUserService、IPasswordServer
// </summary>

// 重载 1:自动从全局 AppSettings.Configuration 读取
builder.Services.AddOmiSystemSetup();

// 重载 2:传入自定义 IConfiguration
builder.Services.AddOmiSystemSetup(configuration.GetSection("MyUserRole"));

// 重载 3:通过 Action 委托配置
builder.Services.AddOmiSystemSetup(options =>
{
    options.InitTable    = true;
    options.InitSeedData = true;
});

// 自定义服务生命周期
builder.Services.AddOmiSystemSetup(ServiceLifetime.Singleton);

// 初始化数据库表结构(SysRole / SysUser / SysUserRole)
builder.Services.AddSystemInitSetup();
参数 类型 默认值 说明
serviceLifetime ServiceLifetime Scoped 注册 5 个服务(SysCacheService / SysRoleService / SysUserRoleService / SysUserService / IPasswordServer)的生命周期
config IConfiguration 自定义配置节
config (Action) Action<DbInitConfig> 代码内配置

⚠️ 线程安全: 切换为 Singleton 生命周期时,确保注入的 SugarRepository<T>ISqlSugarClient 本身支持并发访问。SqlSugar 的 SqlSugarClient 是线程安全的,但仓储的某些操作依赖请求上下文(如 Creator 自动填充、ICurrentUser 身份解析),单例模式下可能导致用户信息串扰。

种子数据说明

InitSeedData = true 时,AddSystemInitSetup 会写入以下预置数据(密码统一为 PasswordConfig.DefaultPassword 加密后的值):

角色 Code 说明
系统管理员 sys_manager_role 拥有系统管理权限(禁止删除)
普通用户 common_role 普通业务角色
用户 Account 管理员类型 关联角色 说明
超级管理员 superAdmin SuperAdmin 系统最高权限用户(不参与分页展示)
系统管理员 admin Admin sys_manager_role 日常管理用户
普通用户 ruovea None common_role 普通业务用户

API 接口速览

所有接口自动归入 Swagger "system" 分组,默认路由前缀由 DynamicWebApi 配置决定(默认 /api,可通过 DefaultApiPrefix 调整)。

SysUserService — 用户管理

HTTP 路由 方法 说明
GET /api/SysUser/GetUserById GetUserById(long userId) 根据用户 Id 获取用户实体
GET /api/SysUser/GetPages GetPagesAsync([FromQuery] PageUserInput) 分页查询用户列表(含角色名称,排除超管)
GET /api/SysUser/GetRoleUserListByRoleId GetRoleUserListByRoleId(long roleId) 获取指定角色下的用户列表(非超管、启用中)
GET /api/SysUser/UserList UserList() 获取用户列表(不含超管)
GET /api/SysUser/GetAll GetAllAsync() 获取全部用户简要列表(仅 ID、账号、姓名)
GET /api/SysUser/GetBaseInfo GetBaseInfo() 查看当前登录用户基本信息
GET /api/SysUser/GetOwnRoleList GetOwnRoleList(long userId) 获取用户拥有角色 Id 集合
POST /api/SysUser/AddUser AddUser(AddUserInput) 增加用户(自动去重 Account、加密密码、同步授权角色)
PUT /api/SysUser/UpdateUser UpdateUser(UpdateUserInput) 更新用户信息(忽略密码和状态字段,同步更新角色)
PUT /api/SysUser/UpdateBaseInfo UpdateBaseInfo(SysUser) 更新当前登录用户基本信息
POST /api/SysUser/SetStatus SetStatus(UserInput) 设置用户状态(启停用,联动黑名单缓存)
DELETE /api/SysUser/DeleteUser DeleteUser(DeleteUserInput) 删除用户(禁止删除超管/自身,级联删除用户角色)
POST /api/SysUser/GrantRole GrantRole(UserRolesInput) 授权用户角色
POST /api/SysUser/ChangePwd ChangePwd(ChangePwdInput) 修改当前用户密码(需验证旧密码,支持强度校验)
POST /api/SysUser/ResetPwd ResetPwd(ResetPwdUserInput) 重置用户密码(管理员操作,重置为默认密码)
POST /api/SysUser/UnlockLogin UnlockLogin(UnlockLoginInput) 解除登录锁定(清空密码错误次数缓存)

SysRoleService — 角色管理

HTTP 路由 方法 说明
GET /api/SysRole/GetPages GetPagesAsync([FromQuery] PageRoleInput) 分页查询角色列表(含权限数据隔离)
GET /api/SysRole/GetList GetList() 获取角色列表(仅启用、按权限范围过滤)
POST /api/SysRole/AddRole AddRole(AddRoleInput) 增加角色(Name/Code 唯一性校验)
PUT /api/SysRole/UpdateRole UpdateRole(AddRoleInput) 更新角色信息
DELETE /api/SysRole/DeleteRole DeleteRole(DeleteRoleInput) 删除角色(禁止删除系统管理员角色、检查关联用户,级联删除用户角色)
POST /api/SysRole/SetStatus SetStatus(RoleInput) 设置角色状态(启停用)

SysUserRoleService — 用户角色关联(内部服务)

HTTP 方法 说明
(内部调用) 授权用户角色 / 授权角色用户
(内部调用) 获取用户角色列表 / 用户角色Id集合 / 角色用户Id集合
(内部调用) 按用户 Id / 角色 Id / 组合键删除关联

此服务不实现 IApplicationService,不对外暴露 HTTP 端点,由 SysUserServiceSysRoleService 内部调用。

SysCacheService — 缓存管理

HTTP 路由 方法 说明
GET /api/SysCache/GetValue GetValue(string key) 根据键名获取缓存值
GET /api/SysCache/GetKeysByPrefixKey GetKeysByPrefixKey(string prefixKey) 根据键名前缀获取键名集合
DELETE /api/SysCache/Remove Remove(string key) 删除指定缓存
DELETE /api/SysCache/RemoveByPrefixKey RemoveByPrefixKey(string prefixKey) 根据键名前缀批量删除缓存
DELETE /api/SysCache/Clear Clear(string profix = "RuoVea*") 清空所有缓存

SysCacheService 中的 Set / Get<T> / ExistKey / AdGetAsync<T> 等均为 [NonAction] 内部方法,仅供服务内部调用,不暴露为 HTTP 端点。


错误处理与日志

错误码速查

组件内部使用 i18n 国际化资源管理错误信息,支持中文本地化。以下为本组件服务实际抛出的核心错误码:

错误码 含义 触发场景
account_exists 账号已存在 增加/更新用户时 Account 重复
account_not_exists 账号不存在 删除/修改/查询的用户不存在
data_exists 数据已存在 创建角色时 Name/Code 重复
dict_status_error 字典状态错误 设置用户/角色状态时 IsDisable 不是合法枚举值
illegal_operation_self 非法操作,禁止删除自己 用户尝试删除自身账号
new_password_same_as_old 新密码不能与旧密码相同 修改密码时新旧密码一致
password_error 旧密码输入错误 修改密码时旧密码验证失败
prohibit_delete_admin 禁止删除系统管理员角色 尝试删除 sys_manager_role 角色
prohibit_delete_super_admin 禁止删除超级管理员 尝试删除 superAdmin 用户
prohibit_modify_self_status 禁止修改本人账号状态 用户尝试启用/停用自身账号
prohibit_modify_super_admin_status 禁止修改超级管理员状态 尝试修改 superAdmin 的状态
record_not_exists 记录不存在 根据 ID 查询/更新时记录缺失
role_has_accounts 此角色下面存在账号禁止删除 删除角色时有关联用户

上述错误码均以 AggregateException 抛出;共享的 i18n.resx 中另包含机构、职位、菜单等模块的错误码,由对应模块使用,本组件不会触发。

异常处理示例

// <summary>
// 安全创建用户 —— 捕获账号重复、参数验证和密码强度异常。
// </summary>
public async Task<(bool Success, string Message)> SafeCreateUserAsync(
    SysUserService userService, AddUserInput input)
{
    try
    {
        var result = await userService.AddUser(input);
        return (result > 0, "用户创建成功");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("account_exists"))
    {
        // 账号已存在
        return (false, $"账号 '{input.Account}' 已被注册");
    }
    catch (ArgumentException ex)
    {
        // 其他业务校验失败
        return (false, $"业务校验失败: {ex.Message}");
    }
    catch (AggregateException ex)
    {
        // 字段级验证失败(密码强度、必填字段等)
        return (false, $"字段验证失败: {ex.Message}");
    }
}

// <summary>
// 安全删除角色 —— 捕获级联检查异常。
// </summary>
public async Task<(bool Success, string Message)> SafeDeleteRoleAsync(
    SysRoleService roleService, long roleId)
{
    try
    {
        await roleService.DeleteRole(new DeleteRoleInput { Id = roleId });
        return (true, "角色删除成功");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("prohibit_delete_admin"))
    {
        return (false, "系统管理员角色禁止删除");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("role_has_accounts"))
    {
        return (false, "该角色下存在关联用户,请先解除所有用户授权后再删除");
    }
    catch (Exception ex)
    {
        return (false, $"删除失败: {ex.Message}");
    }
}

// <summary>
// 同步写法 —— 安全修改用户状态。
// ⚠️ 仅推荐在非 ASP.NET 上下文使用。
// </summary>
public (bool Success, string Message) SafeSetUserStatus(SysUserService userService, long userId, bool disable)
{
    try
    {
        userService.SetStatus(new UserInput
        {
            Id        = userId,
            IsDisable = disable ? YesOrNot.Y : YesOrNot.N
        }).GetAwaiter().GetResult();

        return (true, disable ? "用户已停用" : "用户已启用");
    }
    catch (Exception ex)
    {
        return (false, ex.Message);
    }
}

日志集成

组件不直接输出日志,依赖调用方集成的日志框架。推荐在 Program.cs 中配置 Serilog 或 NLog 来捕获:

// SqlSugar 的 SQL 日志可通过 AOP 事件捕获
builder.Services.AddSqlSugarSetup(); // 内部配置了 SQL 执行日志

// ExFilter 的全局异常拦截会自动记录异常日志
builder.Services.RequestActionSetup()   // 请求日志拦截
               .ExceptionSetup();       // 异常捕获与记录

版本迁移指南

从 8.0.3.x 升级到 10.0.1.x

变更项 说明
TFM 升级 net8.0net10.0,需同步升级所有依赖包到 10.0.* 版本
包版本对齐 RuoVea.ExFilterRuoVea.ExJwtBearerRuoVea.ExPwsRuoVea.OmiApi.ConfigRuoVea.DynamicWebApiRuoVea.ExSugar 均需升至对应 10.0.*
API 兼容 所有公开 API 向后兼容,无需修改业务代码
数据库 表结构无变更,无需执行迁移脚本
密码加密 IPasswordServer 接口不变,加密算法向后兼容

API 变更历史

版本 变更
8.0.3.8 / 10.0.1.6 当前版本
8.0.3.x 密码配置统一为 PasswordConfig(DefaultPassword / StrongPassword),角色列表/分页增加当前用户角色可见性过滤,增加角色用户列表查询等
8.0.2.x 稳定版本
8.0.2.16 修复多字段查询时 SqlSugar 因重复参数 @value 键报错的问题
8.0.2.15 组件版本升级,图表数据缓存
8.0.2.14 表结构初始化处理
更早版本 初始发布

常见问题

Q: 如何切换数据库?

修改 appsettings.json 中的 DbTypeConnectionString,然后重新运行。AddSystemInitSetup 会自动为新数据库创建表结构。

// MySql 示例
{ "DbType": "MySql", "ConnectionString": "Server=localhost;Database=ruovea;Uid=root;Pwd=123456;" }

// SqlServer 示例
{ "DbType": "SqlServer", "ConnectionString": "Server=.;Database=ruovea;Trusted_Connection=True;" }

// PostgreSQL 示例
{ "DbType": "PostgreSQL", "ConnectionString": "Host=localhost;Database=ruovea;Username=postgres;Password=123456;" }

Q: 如何自定义 API 路由前缀?

AddDynamicWebApi 中配置 DefaultApiPrefix

builder.Services.AddDynamicWebApi(options =>
{
    options.DefaultApiPrefix = "/openapi/api";
    options.RemoveControllerPostfixes = new List<string> { "AppService", "Service" };
    options.RemovePrefix = new List<string> { "get", "post" };
});

Q: 如何实现多租户数据隔离?

SysUserSysRole 实体实现了 ITenantEntity 接口。在 ConnectionConfigs 中启用 IsTenantIdFilter: true,SqlSugar 会自动在查询中追加 TenantId 过滤条件。同时需要在 ICurrentUser 实现中返回当前租户 ID。

{
  "ConnectionConfigs": [
    {
      "DbType": "MySql",
      "ConnectionString": "...",
      "IsTenantIdFilter": true
    }
  ]
}

Q: ⚠️ 种子数据的默认密码是什么?如何修改?

种子数据中所有用户的密码均使用 IPasswordServer 加密后写入,默认密码由配置中的 PasswordConfig 配置节(DefaultPassword)控制。如需修改种子用户的默认密码,请修改 AddSystemInitSetup 初始化逻辑中传入的密码明文,或在初始化后通过 ResetPwd 接口重置。

Q: ❗ 为什么 GetPagesAsync 返回的角色列表与预期不符?

角色查询会自动执行权限数据隔离

  • 超级管理员(superAdmin)和系统管理员(admin)可以查看所有角色
  • 普通用户只能查看自己创建的或已拥有的角色

如果登录用户不是超管/系统管理员,查询结果为当前用户权限范围内的角色,并非全部角色。

Q: ChangePwdResetPwd 有什么区别?

方法 使用场景 是否需要旧密码 权限要求
ChangePwd 用户自主修改密码 需要 需要登录(JWT Token)
ResetPwd 管理员重置他人密码 不需要 管理员权限

Q: 删除用户/角色时被阻止怎么办?

组件内置了安全保护检查:

  • 删除用户被阻止:检查是否为 prohibit_delete_super_admin(禁止删除超管)或 illegal_operation_self(禁止删除自己)
  • 删除角色被阻止:检查是否为 prohibit_delete_admin(禁止删除管理员角色)或 role_has_accounts(角色下有关联用户)

对于 role_has_accounts,请先通过 SysUserRoleService 解除所有用户与角色的关联,再执行角色删除。

Q: 缓存服务的底层实现是什么?

SysCacheService 基于 RuoVea.ExCache.CacheFactery 实现,底层可使用 Redis、MemoryCache 或自定义缓存提供程序。缓存键名建议使用 : 分隔的命名空间前缀(如 user:info:1001role:list),便于通过 RemoveByPrefixKey 批量清理。


许可证

本项目基于 Apache 2.0 License 开源发布。


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 (1)

Showing the top 1 NuGet packages that depend on RuoVea.OmiApi.UserRole:

Package Downloads
RuoVea.OmiUserRole

用户角色管理

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.1.8 87 8/20/2026
10.0.1.7 92 8/18/2026
10.0.1.6 95 8/16/2026
10.0.1.5 88 8/16/2026
10.0.1.4 88 8/15/2026
10.0.1.3 88 8/15/2026
10.0.1.2 94 8/15/2026
10.0.1.1 91 8/15/2026
10.0.1 85 8/16/2026
10.0.0.12 106 7/27/2026
8.0.3.10 82 8/20/2026
8.0.3.9 94 8/18/2026
8.0.3.6 95 8/16/2026
8.0.3.5 91 8/16/2026
8.0.3.4 81 8/15/2026
8.0.3.3 87 8/15/2026
8.0.3.2 93 8/15/2026
8.0.3 111 8/16/2026
8.0.2.26 101 7/27/2026
8.0.2.25 97 7/26/2026
Loading failed