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 决定是否注册停机清理钩子
This commit is contained in:
+26
-11
@@ -94,7 +94,7 @@ builder.Services.AddCors(opts => opts.AddDefaultPolicy(p =>
|
||||
// PLATFORM__JWT__SECRET,占位值会被运行时随机化并强制告警。
|
||||
// - InternalTokenStore 管理 SimpleLite 8222 ↔ MiGu.Server 之间的 X-Platform-Internal-Token
|
||||
// 共享密钥(YARP transform 自动追加)。
|
||||
builder.Services.AddSingleton<UserStore>();
|
||||
builder.Services.AddSingleton<RbacStore>();
|
||||
builder.Services.AddSingleton<JwtIssuer>(sp =>
|
||||
{
|
||||
var config = sp.GetRequiredService<IConfiguration>();
|
||||
@@ -145,6 +145,14 @@ builder.Services.AddAuthorization(opts =>
|
||||
opts.AddPolicy("MonitorScope", p => p.RequireAuthenticatedUser().RequireClaim("scope", "RCSMonitor"));
|
||||
// 任一登录用户。
|
||||
opts.AddPolicy("AnyAuthed", p => p.RequireAuthenticatedUser());
|
||||
// RBAC 管理:JWT 的 ops claim(空格分隔)含 "*" 或 "auth.manage" 才放行。
|
||||
// 用于 RbacController(用户 / 角色 / 权限页面管理),即「超级管理员」类账号专属。
|
||||
opts.AddPolicy("RbacAdmin", p => p.RequireAuthenticatedUser().RequireAssertion(ctx =>
|
||||
{
|
||||
var ops = ctx.User.FindFirst("ops")?.Value ?? string.Empty;
|
||||
var set = ops.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
return set.Contains("*") || set.Contains("auth.manage");
|
||||
}));
|
||||
});
|
||||
|
||||
// YARP + transform:把 Platform 内部 token 透传给 SimpleLite 8222(AR-1/AR-2 配套)。
|
||||
@@ -176,24 +184,31 @@ var app = builder.Build();
|
||||
// 启动期主动构造 JwtIssuer / InternalTokenStore:让 secret 校验日志在请求来之前打印。
|
||||
_ = app.Services.GetRequiredService<JwtIssuer>();
|
||||
_ = app.Services.GetRequiredService<InternalTokenStore>();
|
||||
// 主动实例化 SimpleLiteLauncher,让 ProcessExit 钩子尽早注册(MiGu.Server 异常退出时 SimpleLite 也会被清理)。
|
||||
// 主动构造 RbacStore:首启时尽早 seed 默认用户 / 角色并打印 data/rbac.json 载入日志。
|
||||
_ = app.Services.GetRequiredService<RbacStore>();
|
||||
// 主动实例化 SimpleLiteLauncher(FollowParent=true 时注册 ProcessExit 软关闭钩子)。
|
||||
var simpleLiteLauncher = app.Services.GetRequiredService<SimpleLiteLauncher>();
|
||||
{
|
||||
var sl = simpleLiteLauncher.GetDiagnostics();
|
||||
app.Logger.LogInformation(
|
||||
"[MiGu.Server] SimpleLite: Enabled={Enabled}, ConfiguredPath={Cfg}, Resolved={Resolved}, Exists={Exists}, Port:{Port} reachable={PortUp}. 配置见 appsettings.json → SimpleLite",
|
||||
sl.Enabled, sl.ConfiguredExecutablePath, sl.ResolvedExecutablePath ?? "(未找到)", sl.ExecutableExists,
|
||||
"[MiGu.Server] SimpleLite: Enabled={Enabled}, FollowParent={FollowParent}, ConfiguredPath={Cfg}, Resolved={Resolved}, Exists={Exists}, Port:{Port} reachable={PortUp}. 配置见 appsettings.json → SimpleLite",
|
||||
sl.Enabled, sl.FollowParent, sl.ConfiguredExecutablePath, sl.ResolvedExecutablePath ?? "(未找到)", sl.ExecutableExists,
|
||||
sl.ProjectionPort, sl.ProjectionPortReachable);
|
||||
}
|
||||
|
||||
// MiGu.Server 停机时是否带走 SimpleLite,由 SimpleLiteLauncher.Dispose 内部按 FollowParent 决定:
|
||||
// - 会话 N+2 起 FollowParent=false 默认值 → Dispose 仅释放本地引用,不 kill 子进程(独立程序语义);
|
||||
// - 仅当用户显式 opt-in FollowParent=true 时,Dispose 才会 kill 子进程 + 关闭 JobObject。
|
||||
app.Lifetime.ApplicationStopping.Register(() =>
|
||||
// FollowParent=true 时 MiGu.Server 退出会 kill SimpleLite;默认 false 时不注册停机清理(两进程独立)。
|
||||
if (builder.Configuration.GetValue("SimpleLite:FollowParent", false))
|
||||
{
|
||||
try { app.Services.GetRequiredService<SimpleLiteLauncher>().Dispose(); }
|
||||
catch { /* shutdown best-effort */ }
|
||||
});
|
||||
app.Lifetime.ApplicationStopping.Register(() =>
|
||||
{
|
||||
try { app.Services.GetRequiredService<SimpleLiteLauncher>().Dispose(); }
|
||||
catch { /* shutdown best-effort */ }
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
app.Logger.LogInformation("[MiGu.Server] SimpleLite: FollowParent=false — MiGu.Server 退出不会结束 SimpleLite");
|
||||
}
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user