From 0208edb9edd21a20fca975361a7641f25f008cda Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Tue, 4 Jul 2023 15:24:06 +0800 Subject: [PATCH 1/3] =?UTF-8?q?hang=5FS=5F1=5F=E5=8F=AF=E9=80=86=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E7=AE=97=E6=B3=95=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_IRaCIS/SymmetricEncryption.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 IRaCIS.Core.Infrastructure/_IRaCIS/SymmetricEncryption.cs diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/SymmetricEncryption.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/SymmetricEncryption.cs new file mode 100644 index 000000000..f19c5dd73 --- /dev/null +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/SymmetricEncryption.cs @@ -0,0 +1,46 @@ +using System; +using System.Security.Cryptography; +using System.Text; + +namespace IRaCIS.Core.Infrastructure +{ + public class SymmetricEncryption + { + public static string Encrypt(string plainText, string key) + { + byte[] keyBytes = Encoding.UTF8.GetBytes(key); + byte[] ivBytes = new byte[16]; // Initialization vector (IV) + + using (Aes aes = Aes.Create()) + { + aes.Key = keyBytes; + aes.IV = ivBytes; + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); + byte[] encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); + return Convert.ToBase64String(encryptedBytes); + } + } + + public static string Decrypt(string cipherText, string key) + { + byte[] keyBytes = Encoding.UTF8.GetBytes(key); + byte[] ivBytes = new byte[16]; // Initialization vector (IV) + + using (Aes aes = Aes.Create()) + { + aes.Key = keyBytes; + aes.IV = ivBytes; + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + byte[] cipherBytes = Convert.FromBase64String(cipherText); + byte[] decryptedBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); + return Encoding.UTF8.GetString(decryptedBytes); + } + } + } + + + +} From 891af745bb04e1fc84df709dd2412fa2f2f630a5 Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Tue, 4 Jul 2023 17:02:51 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Management/DTO/UserLogViewModel.cs | 55 +++++++++++++++ .../Management/Interface/IUserLogService.cs | 24 +++++++ .../Service/Management/UserLogService.cs | 67 ++++++++++++++++++ .../Service/Management/UserService.cs | 41 ++++------- .../Service/Management/_MapConfig.cs | 3 +- IRaCIS.Core.Domain/Management/UserLog.cs | 70 +++++++++++++++++++ .../Context/IRaCISDBContext.cs | 2 + 7 files changed, 234 insertions(+), 28 deletions(-) create mode 100644 IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs create mode 100644 IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs create mode 100644 IRaCIS.Core.Application/Service/Management/UserLogService.cs create mode 100644 IRaCIS.Core.Domain/Management/UserLog.cs diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs new file mode 100644 index 000000000..40d69d0c6 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:46 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- +using System; +using IRaCIS.Core.Domain.Share; +using System.Collections.Generic; +namespace IRaCIS.Core.Application.ViewModel +{ + /// UserLogView 列表视图模型 + public class UserLogView: UserLogAddOrEdit + { + + + public string UserRealName { get; set; } + public string UserName { get; set; } + + public UserType UserTypeEnum { get; set; } + + public bool IsSuccess { get; set; } + + } + + ///UserLogQuery 列表查询参数模型 + public class UserLogQuery : PageInput + { + public UserOptType? OptType { get; set; } + + public string? IP { get; set; } + + public string? LoginName { get; set; } + + public DateTime? BeginDate { get; set; } + + public DateTime? EndDate { get; set; } + + + } + + /// UserLogAddOrEdit 列表查询参数模型 + public class UserLogAddOrEdit + { + public Guid? Id { get; set; } + public string IP { get; set; } + + public string LoginName { get; set; } + public int OptType { get; set; } + public string LoginPassword { get; set; } + } + + +} + + diff --git a/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs b/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs new file mode 100644 index 000000000..521f71870 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs @@ -0,0 +1,24 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:34 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- + +using IRaCIS.Core.Application.ViewModel; +namespace IRaCIS.Core.Application.Interfaces +{ + /// + /// IUserLogService + /// + public interface IUserLogService + { + + Task> GetUserLogList(UserLogQuery inQuery); + + //Task AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog); + + //Task DeleteUserLog(Guid userLogId); + + + } +} diff --git a/IRaCIS.Core.Application/Service/Management/UserLogService.cs b/IRaCIS.Core.Application/Service/Management/UserLogService.cs new file mode 100644 index 000000000..1aaf7aa27 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/UserLogService.cs @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:37 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- + +using IRaCIS.Core.Domain.Models; +using Microsoft.AspNetCore.Mvc; +using IRaCIS.Core.Application.Interfaces; +using IRaCIS.Core.Application.ViewModel; +namespace IRaCIS.Core.Application.Service +{ + /// + /// UserLogService + /// + [ApiExplorerSettings(GroupName = "Test")] + public class UserLogService : BaseService, IUserLogService + { + + private readonly IRepository _userLogRepository; + + public UserLogService(IRepository userLogRepository) + { + _userLogRepository = userLogRepository; + } + + public async Task> GetUserLogList(UserLogQuery inQuery) + { + + var userLogQueryable = + + _userLogRepository + .WhereIf(inQuery.OptType!=null ,t=>t.OptType==inQuery.OptType) + .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) + .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName) , t => t.LoginName.Contains(inQuery.LoginName) ) + .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP)) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName), t => t.LoginName.Contains(inQuery.LoginName)) + .ProjectTo(_mapper.ConfigurationProvider); + + var pageList = await userLogQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? "Id" : inQuery.SortField,inQuery.Asc); + + return pageList; + } + + + //public async Task AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog) + //{ + // // 在此处拷贝automapper 映射 + + // var entity = await _userLogRepository.InsertOrUpdateAsync(addOrEditUserLog, true); + + // return ResponseOutput.Ok(entity.Id.ToString()); + + //} + + + //[HttpDelete("{userLogId:guid}")] + //public async Task DeleteUserLog(Guid userLogId) + //{ + // var success = await _userLogRepository.DeleteFromQueryAsync(t => t.Id == userLogId, true); + // return ResponseOutput.Ok(); + //} + + + } +} diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 2de18aeea..9305f852c 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -27,6 +27,7 @@ namespace IRaCIS.Application.Services private readonly IOptionsMonitor _verifyConfig; + private readonly IRepository _userLogRepository; public UserService(IRepository userRepository, @@ -36,7 +37,8 @@ namespace IRaCIS.Application.Services IMemoryCache cache, IRepository userTrialRepository, IOptionsMonitor verifyConfig - +, + IRepository userLogRepository ) { _verifyConfig = verifyConfig; @@ -46,6 +48,7 @@ namespace IRaCIS.Application.Services _verificationCodeRepository = verificationCodeRepository; _doctorRepository = doctorRepository; _userTrialRepository = userTrialRepository; + _userLogRepository = userLogRepository; } @@ -639,6 +642,8 @@ namespace IRaCIS.Application.Services if (failCount >= maxFailures) { + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.AccountLocked }, true); + throw new BusinessValidationFailedException($"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。"); } @@ -672,6 +677,8 @@ namespace IRaCIS.Application.Services failCount++; _cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.PasswordError }, true); + return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new LoginReturnDTO()); @@ -688,7 +695,7 @@ namespace IRaCIS.Application.Services //登录成功 清除缓存 _cache.Set(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes)); - + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = loginUser.Id, LoginName = userName, IsSuccess = true, OptType = UserOptType.Login }, true); userLoginReturnModel.BasicInfo = loginUser; @@ -701,32 +708,12 @@ namespace IRaCIS.Application.Services - //private bool loginIsLocked(string userName) - //{ + public async Task LoginOut(Guid userId,string loginName) + { + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = userId, LoginName = loginName, IsSuccess = true, OptType = UserOptType.LoginOut },true); - // //if (failCount == null) - // //{ - // // failCount = 0; - // //} - // //else - // //{ - // // failCount++; - // //} - - // //// 更新缓存中的登录失败次数 - // //_cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); - - // //if (failCount >= maxFailures) - // //{ - // // // 如果登录失败次数达到了 3 次,则锁定用户 - // // _cache.Set(cacheKey + ":locked", true, TimeSpan.FromMinutes(lockoutMinutes)); - // //} - - - - - // //return isLocked; - //} + return ResponseOutput.Ok(); + } } } diff --git a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs index fa77bf4c8..842de95ca 100644 --- a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs @@ -119,7 +119,8 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.UserTypeId, c => c.MapFrom(t => t)); - + CreateMap(); + CreateMap().ReverseMap(); } } diff --git a/IRaCIS.Core.Domain/Management/UserLog.cs b/IRaCIS.Core.Domain/Management/UserLog.cs new file mode 100644 index 000000000..923eb84f2 --- /dev/null +++ b/IRaCIS.Core.Domain/Management/UserLog.cs @@ -0,0 +1,70 @@ + +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:43 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +using System; +using IRaCIS.Core.Domain.Share; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +namespace IRaCIS.Core.Domain.Models +{ + /// + ///UserLog + /// + [Table("UserLog")] + public class UserLog : Entity, IAuditAdd + { + + + + + public string IP { get; set; } + + + public DateTime CreateTime { get; set; } + + + public Guid CreateUserId { get; set; } + + + public string LoginName { get; set; } + + + public UserOptType OptType { get; set; } + + + public string LoginPassword { get; set; } + + public bool IsSuccess { get; set; } + + } + + /// + /// 登录或者登出 锁定类型 + /// + public enum UserOptType + { + + /// + /// 用户登录 + /// + Login = 1, + + /// + /// 用户登出 + /// + LoginOut = 2, + + /// + /// 密码错误 + /// + PasswordError = 3, + + /// + /// 账号锁定 + /// + AccountLocked = 4 + } + +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 3d8ac8b8d..344cd1c73 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -508,6 +508,8 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet ReadingTableQuestionAnswer { get; set; } public virtual DbSet PublishLog { get; set; } + public virtual DbSet UserLog { get; set; } + From ac3eaea3f64169fd3e2f720c19afe7346b42ffbf Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Wed, 5 Jul 2023 09:35:38 +0800 Subject: [PATCH 3/3] =?UTF-8?q?hang-S-002=E5=A2=9E=E5=8A=A0=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E9=87=8D=E7=BD=AE=E5=AF=86=E7=A0=81=EF=BC=8C=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/Management/DTO/UserLogViewModel.cs | 2 ++ .../Service/Management/UserLogService.cs | 10 +++++++--- .../Service/Management/UserService.cs | 9 +++++++-- IRaCIS.Core.Domain/Management/UserLog.cs | 14 +++++++++++--- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs index 40d69d0c6..69021f38e 100644 --- a/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs +++ b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs @@ -25,6 +25,8 @@ namespace IRaCIS.Core.Application.ViewModel ///UserLogQuery 列表查询参数模型 public class UserLogQuery : PageInput { + public Guid? TrialId { get; set; } + public UserOptType? OptType { get; set; } public string? IP { get; set; } diff --git a/IRaCIS.Core.Application/Service/Management/UserLogService.cs b/IRaCIS.Core.Application/Service/Management/UserLogService.cs index 1aaf7aa27..b1233aaad 100644 --- a/IRaCIS.Core.Application/Service/Management/UserLogService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserLogService.cs @@ -18,21 +18,25 @@ namespace IRaCIS.Core.Application.Service { private readonly IRepository _userLogRepository; + private readonly IRepository _trialUserRepository; - public UserLogService(IRepository userLogRepository) + public UserLogService(IRepository userLogRepository, IRepository trialUserRepository) { _userLogRepository = userLogRepository; + _trialUserRepository = trialUserRepository; } + public async Task> GetUserLogList(UserLogQuery inQuery) { var userLogQueryable = _userLogRepository + .WhereIf(inQuery.TrialId != null, t => t.CreateUser.UserTrials.Any(c => c.TrialId == inQuery.TrialId && c.UserId == t.CreateUserId)) .WhereIf(inQuery.OptType!=null ,t=>t.OptType==inQuery.OptType) - .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) - .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) + .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) + .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName) , t => t.LoginName.Contains(inQuery.LoginName) ) .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP)) .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName), t => t.LoginName.Contains(inQuery.LoginName)) diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 9305f852c..db3c324d9 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -295,6 +295,8 @@ namespace IRaCIS.Application.Services IsFirstAdd = true }); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName = _userInfo.UserName, IsSuccess = true, OptType = UserOptType.AdminResetPassword }, true); + return ResponseOutput.Ok(); } @@ -405,6 +407,8 @@ namespace IRaCIS.Application.Services IsFirstAdd = false }); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName =string.Empty,LoginPassword=newPwd, IsSuccess = true, OptType = UserOptType.ModifyPassword }, true); + return ResponseOutput.Result(success); } @@ -439,6 +443,7 @@ namespace IRaCIS.Application.Services IsFirstAdd = false }); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName = _userInfo.UserName, IsSuccess = true, OptType = UserOptType.ModifyPassword }, true); return ResponseOutput.Result(success); @@ -642,7 +647,7 @@ namespace IRaCIS.Application.Services if (failCount >= maxFailures) { - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.AccountLocked }, true); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName,LoginPassword=password, IsSuccess = false, OptType = UserOptType.AccountLocked }, true); throw new BusinessValidationFailedException($"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。"); } @@ -677,7 +682,7 @@ namespace IRaCIS.Application.Services failCount++; _cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.PasswordError }, true); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, LoginPassword = password, IsSuccess = false, OptType = UserOptType.AccountOrPasswordError }, true); return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new LoginReturnDTO()); diff --git a/IRaCIS.Core.Domain/Management/UserLog.cs b/IRaCIS.Core.Domain/Management/UserLog.cs index 923eb84f2..0c78d92d0 100644 --- a/IRaCIS.Core.Domain/Management/UserLog.cs +++ b/IRaCIS.Core.Domain/Management/UserLog.cs @@ -38,6 +38,10 @@ namespace IRaCIS.Core.Domain.Models public bool IsSuccess { get; set; } + + [JsonIgnore] + public User CreateUser { get; set; } + } /// @@ -57,14 +61,18 @@ namespace IRaCIS.Core.Domain.Models LoginOut = 2, /// - /// 密码错误 + ///账号或者密码错误 /// - PasswordError = 3, + AccountOrPasswordError = 3, /// /// 账号锁定 /// - AccountLocked = 4 + AccountLocked = 4, + + ModifyPassword=5, + + AdminResetPassword=6 } }