Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Service/AdminAuthService.cs
glz 77778f67c1 feat: 新增SDK模块、OSS相关功能并优化Redis与代码扩展
1.  新增API版本枚举SDK项,创建SDK基础控制器
2.  添加IList、string扩展方法,新增时间戳扩展工具
3.  新增OSS配置、STS凭证服务、文件处理相关代码
4.  重构Redis缓存组件,替换StackExchange.Redis为CSRedisCore
5.  修复原有Redis操作方法调用,新增基础控制器快捷返回方法
6.  新增阿里云OSS、短信、VOD相关SDK依赖
7.  配置阿里云OSS相关参数到appsettings
2026-06-09 14:36:46 +08:00

160 lines
5.6 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 BCrypt.Net;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.Infrastructure.Auth;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Settings;
using QYZH.InteractiveMagazine.Repository;
namespace QYZH.InteractiveMagazine.Service;
public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, IConfiguration configuration, ILogger<AdminAuthService> logger) : BaseRepository<AdminUser>, IAdminAuthService
{
private const string TokenKeyPrefix = "InteractiveMagazine:AdminAuth:Token";
private const string UserInfoKeyPrefix = "InteractiveMagazine:AdminAuth:UserInfo";
public async Task<AdminLoginOutput> LoginAsync(AdminLoginInput input)
{
logger.LogInformation("管理员登录尝试,用户名: {UserName}", input.UserName);
if (string.IsNullOrWhiteSpace(input.UserName))
{
throw new BusinessException("用户名不能为空", 400);
}
if (string.IsNullOrWhiteSpace(input.Password))
{
throw new BusinessException("密码不能为空", 400);
}
var adminUser = await adminUserRepository.GetFirstAsync(a => a.UserName == input.UserName);
if (adminUser == null)
{
logger.LogWarning("管理员登录失败,用户名不存在: {UserName}", input.UserName);
throw new BusinessException("用户名或密码错误", 401);
}
if (!BCrypt.Net.BCrypt.Verify(input.Password, adminUser.PasswordHash))
{
logger.LogWarning("管理员登录失败,密码错误: {UserName}", input.UserName);
throw new BusinessException("用户名或密码错误", 401);
}
if (adminUser.Status != 1)
{
logger.LogWarning("管理员登录失败,账号已禁用: {UserName}", input.UserName);
throw new BusinessException("账号已被禁用,请联系系统管理员", 403);
}
var jwtSettings = GetJwtSettings();
var token = JwtHelper.GenerateToken((long)adminUser.Id, adminUser.UserName, jwtSettings);
await RedisHelper.SetAsync($"{TokenKeyPrefix}:{adminUser.Id}", token, TimeSpan.FromMinutes(jwtSettings.ExpiryMinutes));
logger.LogInformation("管理员登录成功,用户名: {UserName}, ID: {UserId}", input.UserName, adminUser.Id);
return new AdminLoginOutput
{
Token = token,
UserId = (long)adminUser.Id,
UserName = adminUser.UserName,
Type = adminUser.Type.ToString(),
};
}
public async Task LogoutAsync(long userId)
{
logger.LogInformation("管理员登出ID: {UserId}", userId);
await RedisHelper.DelAsync($"{TokenKeyPrefix}:{userId}");
logger.LogInformation("管理员登出成功ID: {UserId}", userId);
}
public async Task<AdminUserInfoOutput> GetAdminInfoAsync(long userId)
{
logger.LogInformation("获取管理员信息ID: {UserId}", userId);
var adminUser = await adminUserRepository.GetByIdAsync(userId);
if (adminUser == null)
{
logger.LogWarning("未找到管理员ID: {UserId}", userId);
throw new BusinessException("用户不存在", 404);
}
return new AdminUserInfoOutput
{
UserId = adminUser.Id,
UserName = adminUser.UserName,
Type = adminUser.Type.ToString(),
Status = adminUser.Status
};
}
public async Task ChangePasswordAsync(long userId, string oldPassword, string newPassword)
{
logger.LogInformation("管理员修改密码尝试ID: {UserId}", userId);
if (string.IsNullOrWhiteSpace(oldPassword))
{
throw new BusinessException("原密码不能为空", 400);
}
if (string.IsNullOrWhiteSpace(newPassword))
{
throw new BusinessException("新密码不能为空", 400);
}
var adminUser = await adminUserRepository.GetByIdAsync(userId);
if (adminUser == null)
{
logger.LogWarning("未找到管理员ID: {UserId}", userId);
throw new BusinessException("用户不存在", 404);
}
if (!BCrypt.Net.BCrypt.Verify(oldPassword, adminUser.PasswordHash))
{
logger.LogWarning("管理员修改密码失败原密码错误ID: {UserId}", userId);
throw new BusinessException("原密码错误", 400);
}
adminUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword);
var result = await adminUserRepository.UpdateAsync(adminUser);
if (!result)
{
throw new BusinessException("修改密码失败", 500);
}
await RedisHelper.DelAsync($"{TokenKeyPrefix}:{userId}");
logger.LogInformation("管理员修改密码成功ID: {UserId}", userId);
}
private JwtSettings GetJwtSettings()
{
var jwtSettings = configuration.GetSection("JwtSettings").Get<JwtSettings>()
?? new JwtSettings
{
Issuer = "QYZH.InteractiveMagazine",
Audience = "QYZH.InteractiveMagazine",
SecretKey = "your-256-bit-secret-key-here-change-in-production",
ExpiryMinutes = 120
};
if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey))
{
throw new BusinessException("JWT 配置不完整", 500);
}
return jwtSettings;
}
}