- 新增 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 决定是否注册停机清理钩子
83 lines
3.1 KiB
C#
83 lines
3.1 KiB
C#
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);
|