using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using System.Security.Claims; using RainOpsMini.Helpers; using RainOpsMini.Models; using RainOpsMini; namespace RainOpsMini.Apis { public static class AuthApi { public static void MapAuthApis(this IEndpointRouteBuilder app) { // API: 获取验证码 // 生成图形验证码用于登录验证 app.MapGet("/api/captcha", (IMemoryCache cache) => { var (code, svg) = CaptchaHelper.GenerateCaptcha(); var id = Guid.NewGuid().ToString(); // 缓存验证码,有效期 5 分钟 cache.Set(id, code, TimeSpan.FromMinutes(5)); return Results.Ok(new { id, svg }); }); // API: 用户登录 // 验证用户名密码和验证码,发放 Cookie app.MapPost("/api/login", async (LoginRequest req, HttpContext ctx, IMemoryCache cache) => { // 校验验证码 if (string.IsNullOrEmpty(req.CaptchaId) || string.IsNullOrEmpty(req.CaptchaCode)) { return Results.BadRequest(new { error = "请输入验证码" }); } if (!cache.TryGetValue(req.CaptchaId, out string? correctCode) || correctCode == null) { return Results.BadRequest(new { error = "验证码已过期,请刷新" }); } if (!string.Equals(correctCode, req.CaptchaCode, StringComparison.OrdinalIgnoreCase)) { return Results.BadRequest(new { error = "验证码错误" }); } // 移除已使用的验证码 cache.Remove(req.CaptchaId); // 1. 检查超级管理员账号 (配置文件中定义) // 使用 Program.config 访问全局配置 if (req.Username == Program.Config.WebUser && req.Password == Program.Config.WebPassword) { var claims = new List { new Claim(ClaimTypes.Name, req.Username), new Claim("IsSuperAdmin", "true"), new Claim("Permission", "all") }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { IsPersistent = true }; // 记录登录日志 try { using (var db = DbHelper.GetInstance()) { db.Insertable(new RainOpsMini.Models.UserLoginLog { Username = req.Username, LoginTime = DateTime.Now, IpAddress = ctx.Connection.RemoteIpAddress?.ToString() }).ExecuteCommand(); } } catch (Exception ex) { Console.WriteLine($"Failed to record login: {ex.Message}"); } await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); return Results.Ok(new { redirect = "/", permissions = new List { "all" } }); } // 2. 检查子账号 (数据库中定义) var user = UserStorage.GetByUsername(req.Username); if (user != null && user.IsEnabled && user.Password == req.Password) { var claims = new List { new Claim(ClaimTypes.Name, req.Username), new Claim("IsSuperAdmin", "false") }; // 合并用户权限和角色权限 var effectivePermissions = new HashSet(user.Permissions); if (!string.IsNullOrEmpty(user.RoleId)) { var role = RoleStorage.GetById(user.RoleId); if (role != null) { foreach (var p in role.Permissions) { effectivePermissions.Add(p); } } } foreach (var perm in effectivePermissions) { claims.Add(new Claim("Permission", perm)); } var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { IsPersistent = true }; // 记录登录日志 try { using (var db = DbHelper.GetInstance()) { db.Insertable(new RainOpsMini.Models.UserLoginLog { Username = req.Username, LoginTime = DateTime.Now, IpAddress = ctx.Connection.RemoteIpAddress?.ToString() }).ExecuteCommand(); } } catch (Exception ex) { Console.WriteLine($"Failed to record login: {ex.Message}"); } await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); return Results.Ok(new { redirect = "/", permissions = effectivePermissions.ToList() }); } return Results.Unauthorized(); }); // API: 获取当前用户信息 // 返回当前登录用户的权限和角色信息 app.MapGet("/api/auth/me", (HttpContext ctx) => { if (ctx.User.Identity?.IsAuthenticated != true) return Results.Unauthorized(); var isSuper = ctx.User.FindFirst("IsSuperAdmin")?.Value == "true"; var username = ctx.User.Identity.Name; var perms = new List(); // 重新获取最新权限 (避免 Cookie 中权限过期) if (!isSuper && !string.IsNullOrEmpty(username)) { var user = UserStorage.GetByUsername(username); if (user != null) { var effectivePermissions = new HashSet(user.Permissions); if (!string.IsNullOrEmpty(user.RoleId)) { var role = RoleStorage.GetById(user.RoleId); if (role != null) { foreach (var p in role.Permissions) { effectivePermissions.Add(p); } } } perms = effectivePermissions.ToList(); } } else if (isSuper) { perms.Add("all"); } return Results.Json(new { username, isSuperAdmin = isSuper, permissions = perms }); }); // API: 退出登录 app.MapPost("/api/logout", async (HttpContext ctx) => { await ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Results.Ok(); }); } } }