Files
Migu2.0/MiGu.Server/Auth/RbacModels.cs
T
zhaowei.huang a5dd632898 feat(rbac): RbacStore 持久化权限体系替代硬编码 UserStore
- 新增 PageCatalog / RbacModels / RbacStore / RbacController:用户、角色、页面/操作/控件授权落盘 data/rbac.json,支持运行时增删改并即时生效
- 密码改用 PBKDF2-SHA256(100k 迭代 + 16B 随机盐) 存储,校验走 FixedTimeEquals 防时序攻击;对外 DTO 绝不外泄盐/哈希
- AuthController 登录 / me / switch-scope 统一收敛到 BuildSession,按角色在当前 scope 的并集计算有效权限并签发 JWT
- EffectivePermissions 增加 AllowedPages;移除旧的硬编码 UserStore
- Program.cs 注册 RbacStore、新增 RbacAdmin 授权策略(ops claim 含 * 或 auth.manage),并按 SimpleLite:FollowParent 决定是否注册停机清理钩子
2026-05-29 23:51:08 +08:00

83 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using MiGu.Server.Configs;
namespace MiGu.Server.Auth;
/// <summary>
/// RBAC 角色。一个角色 = 一组「页面 + 操作码 + 控件可见性」授权,归属某个 scope。
/// <list type="bullet">
/// <item><see cref="Scope"/><c>Platform</c> / <c>RCSMonitor</c> / <c>*</c>(通用,对两个 scope 都生效)。</item>
/// <item><see cref="Pages"/>:可访问页面 Key 集合(见 <see cref="PageCatalog"/>);含 <c>*</c> 表示该 scope 全部页面。</item>
/// <item><see cref="Ops"/>:细粒度操作码(如 <c>ops.car.pause</c>);含 <c>*</c> 表示全部操作。</item>
/// <item><see cref="WidgetGrants"/>:控件级可见性(hidden / readonly / interactive)。</item>
/// <item><see cref="System"/>:内置系统角色,禁止删除(可改名/调权限但保底不被误删)。</item>
/// </list>
/// </summary>
public sealed class RbacRole
{
public string Id { get; set; } = "";
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public string Scope { get; set; } = PageCatalog.ScopePlatform;
public List<string> Pages { get; set; } = new();
public List<string> Ops { get; set; } = new();
public List<WidgetGrantDto> WidgetGrants { get; set; } = new();
public bool System { get; set; }
}
/// <summary>
/// RBAC 用户。密码以 PBKDF2-SHA256 哈希存储(<see cref="Salt"/> / <see cref="PasswordHash"/> 均为 base64)。
/// 一个用户可拥有多个角色,其有效权限 = 当前 scope 下各角色授权的并集。
/// </summary>
public sealed class RbacUser
{
public string Id { get; set; } = "";
public string Username { get; set; } = "";
public string DisplayName { get; set; } = "";
public bool Enabled { get; set; } = true;
public List<string> RoleIds { get; set; } = new();
public string Salt { get; set; } = "";
public string PasswordHash { get; set; } = "";
}
/// <summary>rbac.json 的根对象(内存 + 文件持久化)。</summary>
public sealed class RbacSnapshot
{
public int Version { get; set; } = 1;
public List<RbacRole> Roles { get; set; } = new();
public List<RbacUser> Users { get; set; } = new();
}
// ─────────────────────────── API DTO ───────────────────────────
/// <summary>对外用户视图:绝不含 Salt / PasswordHash。<see cref="Scopes"/> 为该用户可登录的 scope 集合。</summary>
public sealed record RbacUserDto(
string Id,
string Username,
string DisplayName,
bool Enabled,
List<string> RoleIds,
List<string> Scopes);
public sealed record CreateUserRequest(
string Username,
string? DisplayName,
string Password,
List<string>? RoleIds,
bool Enabled = true);
public sealed record UpdateUserRequest(
string? DisplayName,
List<string>? RoleIds,
bool? Enabled);
public sealed record SetPasswordRequest(string Password);
public sealed record SaveRoleRequest(
string? Id,
string Name,
string? Description,
string Scope,
List<string>? Pages,
List<string>? Ops,
List<WidgetGrantDto>? WidgetGrants);