Files
squad-rain-ops-mini/Apis/AuthApi.cs

204 lines
8.2 KiB
C#

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<Claim>
{
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<string> { "all" } });
}
// 2. 检查子账号 (数据库中定义)
var user = UserStorage.GetByUsername(req.Username);
if (user != null && user.IsEnabled && user.Password == req.Password)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, req.Username),
new Claim("IsSuperAdmin", "false")
};
// 合并用户权限和角色权限
var effectivePermissions = new HashSet<string>(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<string>();
// 重新获取最新权限 (避免 Cookie 中权限过期)
if (!isSuper && !string.IsNullOrEmpty(username))
{
var user = UserStorage.GetByUsername(username);
if (user != null)
{
var effectivePermissions = new HashSet<string>(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();
});
}
}
}