using Furion.DatabaseAccessor.Extensions;
using Furion.EventBus;
using Microsoft.Extensions.Options;
using UAParser;
using YBEE.EQM.Core;
namespace YBEE.EQM.Application;
///
/// 认证服务
///
public class SysAuthService : ISysAuthService, ITransient
{
private readonly AuthOptions _authOptions;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IEventPublisher _eventPublisher;
private readonly IRepository _userRep;
private readonly ISysRoleService _roleService;
private readonly ISysRoleUserService _roleUserService;
private readonly ISysMenuService _menuService;
private readonly IGeneralCaptchaService _captchaService;
private readonly ICacheService _cacheService;
public SysAuthService(IOptions options,
IHttpContextAccessor httpContextAccessor,
IEventPublisher eventPublisher,
IRepository userRep,
ISysRoleService roleService,
ISysRoleUserService roleUserService,
ISysMenuService menuService,
IGeneralCaptchaService captchaService,
ICacheService cacheService)
{
_authOptions = options.Value;
_httpContextAccessor = httpContextAccessor;
_eventPublisher = eventPublisher;
_userRep = userRep;
_roleService = roleService;
_roleUserService = roleUserService;
_menuService = menuService;
_captchaService = captchaService;
_cacheService = cacheService;
}
///
/// 登录处理
///
/// 账户密码
///
private async Task Login(LoginInput accountLoginInput)
{
var checkCaptcha = _captchaService.CheckCode(accountLoginInput.Captcha);
if (checkCaptcha.Code != 0)
{
throw Oops.Oh(checkCaptcha.Message);
}
string pwd = "";
string newPwd = "";
try
{
pwd = RSAEncryption.Decrypt(accountLoginInput.Password, _authOptions.RsaPrivateKey);
if (!string.IsNullOrEmpty(accountLoginInput.NewPassword))
{
newPwd = RSAEncryption.Decrypt(accountLoginInput.NewPassword, _authOptions.RsaPrivateKey);
if (pwd == newPwd)
{
throw Oops.Oh(ErrorCode.E1009);
}
}
}
catch
{
throw Oops.Oh("密码格式错误!");
}
//// 判断用户名和密码是否正确 忽略全局过滤器
//var users = await _userRep.DetachedEntities
// .Include(t => t.SysOrg)
// .Where(u => (u.Account.Equals(accountLoginInput.Account) || u.Mobile.Equals(accountLoginInput.Account) || u.Email.Equals(accountLoginInput.Account)) && u.IsDeleted == false)
// .ToListAsync();
var user = await _userRep.Include(t => t.SysOrg)
.FirstOrDefaultAsync(u => u.IsDeleted == false &&
(u.Account.Equals(accountLoginInput.Account) ||
u.Mobile.Equals(accountLoginInput.Account) ||
u.Email.Equals(accountLoginInput.Account)
)) ?? throw Oops.Oh(ErrorCode.E1001);
if (!AESEncryption.Decrypt(user.Password, _authOptions.AesPassword).Equals(pwd))
{
throw Oops.Oh(ErrorCode.E1001);
}
//var user = (users?.FirstOrDefault(u => AESEncryption.Decrypt(u.Password, _authOptions.AesPassword).Equals(pwd))) ?? throw Oops.Oh(ErrorCode.E1001);
if (!user.IsActivated && newPwd != "")
{
user.Password = AESEncryption.Encrypt(newPwd, _authOptions.AesPassword);
user.IsActivated = true;
user.ActivateTime = DateTime.Now;
await user.UpdateIncludeNowAsync(new[] { nameof(user.Password), nameof(user.IsActivated), nameof(user.ActivateTime) });
}
AuthOutput ret = new()
{
OrgName = user.SysOrg.Name,
Name = user.Name,
Account = user.Account,
IsActivated = user.IsActivated,
AccessToken = "",
};
if (!user.IsActivated)
{
return ret;
}
// 验证账号是否被冻结
if (user.Status == CommonStatus.DISABLE)
{
throw Oops.Oh(ErrorCode.E1003);
}
var isSuperAdmin = await _roleUserService.IsSuperAdmin(user.Id);
// 生成Token令牌
var accessToken = JWTEncryption.Encrypt(new Dictionary
{
{ClaimConst.CLAINM_USERID, user.Id},
{ClaimConst.CLAINM_ACCOUNT, user.Account},
{ClaimConst.CLAINM_NAME, user.Name},
{ClaimConst.CLAINM_ORGID, user.SysOrgId},
{ClaimConst.CLAINM_ORGNAME, user.SysOrg.Name},
{ClaimConst.CLAINM_SUPERADMIN, isSuperAdmin.ToString()},
});
// 设置Swagger自动登录
_httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
// 生成刷新Token令牌
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions().ExpiredTime);
// 设置刷新Token令牌
_httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
ret.AccessToken = accessToken;
return ret;
}
///
/// 账户密码登录
///
///
///
public async Task LoginByAccount([Required] LoginInput input)
{
return await Login(accountLoginInput: input);
}
///
/// 获取当前登录用户信息
///
///
public async Task GetLoginUser()
{
var user = await _userRep.Include(t => t.SysOrg).FirstOrDefaultAsync(u => u.Id == CurrentSysUserInfo.SysUserId) ?? throw Oops.Oh(ErrorCode.E1002);
var userId = user.Id;
var loginOutput = user.Adapt();
var httpContext = _httpContextAccessor.HttpContext;
loginOutput.LastLoginTime = user.LastLoginTime = DateTime.Now;
loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4();
var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
loginOutput.LastLoginBrowser = client.UA.Family + client.UA.Major;
loginOutput.LastLoginOs = client.OS.Family + client.OS.Major;
// 角色信息
loginOutput.SysRoles = await _roleUserService.GetLoginUserRoleList(userId);
// 权限信息
loginOutput.Permissions = await _menuService.GetLoginPermissionList(userId);
// 系统所有权限信息
loginOutput.AllPermissions = await _menuService.GetAllPermissionList();
// 菜单信息
loginOutput.Menus = await _menuService.GetLoginAntMenus(userId);
// 更新用户最后登录Ip和时间
await _userRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) });
// 增加登录日志
await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
new SysLogVis
{
Name = loginOutput.Name,
Success = true,
Message = "登录成功",
Ip = loginOutput.LastLoginIp,
Browser = loginOutput.LastLoginBrowser,
Os = loginOutput.LastLoginOs,
VisType = LoginType.LOGIN,
VisTime = loginOutput.LastLoginTime,
Account = loginOutput.Account
}));
return loginOutput;
}
///
/// 退出
///
///
public async Task Logout()
{
var ip = _httpContextAccessor.HttpContext.GetRequestIPv4();
_httpContextAccessor.HttpContext.SignoutToSwagger();
//_httpContextAccessor.HttpContext.Response.Headers["access-token"] = "invalid token";
// 增加退出日志
await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
new SysLogVis
{
Name = CurrentSysUserInfo.Name,
Success = true,
Message = "退出成功",
VisType = LoginType.LOGOUT,
VisTime = DateTime.Now,
Account = CurrentSysUserInfo.Account,
Ip = ip
}));
}
///
/// 获取验证码
///
///
public Task GetCaptcha()
{
// 图片大小要与前端保持一致(坐标范围)
return Task.FromResult(_captchaService.CreateCaptchaImage());
}
///
/// 校验验证码
///
///
///
public Task VerifyCaptcha(GeneralCaptchaInput input)
{
return Task.FromResult(_captchaService.CheckCode(input));
}
}