diff --git a/src/TrackCenter.Api/JWTEncryption.cs b/src/TrackCenter.Api/JWTEncryption.cs index 87098d95..2edd00f6 100644 --- a/src/TrackCenter.Api/JWTEncryption.cs +++ b/src/TrackCenter.Api/JWTEncryption.cs @@ -11,17 +11,20 @@ public class JWTEncryption public static TokenValidationParameters CreateTokenValidationParameters( JWTSettingsOptions jwtSettings) { + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)); + return new TokenValidationParameters() { - ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.IssuerSigningKey)), - ValidateIssuer = jwtSettings.ValidateIssuer, - ValidIssuer = jwtSettings.ValidIssuer, - ValidateAudience = jwtSettings.ValidateAudience, - ValidAudience = jwtSettings.ValidAudience, - ValidateLifetime = jwtSettings.ValidateLifetime, - ClockSkew = TimeSpan.FromSeconds(jwtSettings.ClockSkew), - RequireExpirationTime = jwtSettings.RequireExpirationTime + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + ValidIssuer = jwtSettings.Issuer, + ValidAudience = jwtSettings.Audience, + IssuerSigningKey = key, + ClockSkew = TimeSpan.FromSeconds(jwtSettings.ClockSkewMinutes), + // 验证过期时间 + RequireExpirationTime = true }; } } diff --git a/src/TrackCenter.Api/JWTSettingsOptions.cs b/src/TrackCenter.Api/JWTSettingsOptions.cs index 78791b7c..f2959370 100644 --- a/src/TrackCenter.Api/JWTSettingsOptions.cs +++ b/src/TrackCenter.Api/JWTSettingsOptions.cs @@ -4,36 +4,38 @@ namespace TrackCenter.Api; /// Jwt 配置 public sealed class JWTSettingsOptions { - /// 验证签发方密钥 - public bool ValidateIssuerSigningKey { get; set; } + /// + /// 配置节名称 + /// + public static string SectionName = "JwtSettings"; - /// 签发方密钥 - public string IssuerSigningKey { get; set; } + /// + /// 密钥(至少32位字符) + /// + public string SecretKey { get; set; } = "YourSuperSecretKeyThatIsAtLeast32CharactersLong!"; - /// 验证签发方 - public bool ValidateIssuer { get; set; } + /// + /// 签发者 + /// + public string Issuer { get; set; } = "SimpleAdmin"; - /// 签发方 - public string ValidIssuer { get; set; } + /// + /// 受众 + /// + public string Audience { get; set; } = "SimpleAdminClient"; - /// 验证签收方 - public bool ValidateAudience { get; set; } + /// + /// Access Token 过期时间(分钟) + /// + public int ExpiryInMinutes { get; set; } = 60; - /// 签收方 - public string ValidAudience { get; set; } + /// + /// Refresh Token 过期时间(天) + /// + public int RefreshExpiryInDays { get; set; } = 7; - /// 验证生存期 - public bool ValidateLifetime { get; set; } - - /// 过期时间容错值,解决服务器端时间不同步问题(秒) - public long ClockSkew { get; set; } - - /// 过期时间(分钟) - public long ExpiredTime { get; set; } - - /// 加密算法 - public string Algorithm { get; set; } - - /// 验证过期时间,设置 false 永不过期 - public bool RequireExpirationTime { get; set; } = true; + /// + /// 时钟偏移(分钟),用于处理服务器时间差异 + /// + public int ClockSkewMinutes { get; set; } = 5; } diff --git a/src/TrackCenter.Api/TrackCenter.Api.csproj b/src/TrackCenter.Api/TrackCenter.Api.csproj index 9e875b8b..79e9fa41 100644 --- a/src/TrackCenter.Api/TrackCenter.Api.csproj +++ b/src/TrackCenter.Api/TrackCenter.Api.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/TrackCenter.Api/TrackCenterApiModule.cs b/src/TrackCenter.Api/TrackCenterApiModule.cs index b9e6e159..87cf4f69 100644 --- a/src/TrackCenter.Api/TrackCenterApiModule.cs +++ b/src/TrackCenter.Api/TrackCenterApiModule.cs @@ -1,8 +1,10 @@ using Fake.AspNetCore; using Fake.AspNetCore.Auditing; +using Fake.AspNetCore.Mvc; using Fake.AspNetCore.Mvc.Conventions; using Fake.Autofac; using Fake.Modularity; +using Fake.Security.Claims; using FluentValidation.AspNetCore; using Hangfire; using Microsoft.AspNetCore.Authorization; @@ -28,14 +30,19 @@ public class TrackCenterApiModule : FakeModule { private const string DefaultCorsPolicyName = "default"; + public override void PreConfigureServices(ServiceConfigurationContext context) + { + FakeClaimTypes.UserId = "mapId"; + } + public override void ConfigureServices(ServiceConfigurationContext context) { var services = context.Services; var configuration = context.Services.GetConfiguration(); - services.Configure(options => + services.Configure(options => { - options.ScanApplicationServices(); + options.ApplicationServices2Controller(); }); // 配置签名验证选项 @@ -76,10 +83,8 @@ public class TrackCenterApiModule : FakeModule } }); }) - .AddFakeExceptionFilter() - .AddFakeValidationActionFilter() - .AddFakeAspNetCoreAuditing() - .AddFakeUnitOfWorkActionFilter(); + .AddFakeAspNetCoreAuditing(); + services.AddFluentValidationAutoValidation().AddFluentValidationClientsideAdapters(); var otelOptions = new OTelOptions() diff --git a/src/TrackCenter.Api/appsettings.json b/src/TrackCenter.Api/appsettings.json index 8e98eca6..c41ba880 100644 --- a/src/TrackCenter.Api/appsettings.json +++ b/src/TrackCenter.Api/appsettings.json @@ -176,17 +176,12 @@ "EnableSql": true,//启动SQL 默认 true "EnableSqlParameters": true //启动SQL参数,默认 false }, - "JWTSettings": { - "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true - "IssuerSigningKey": "3c1cbc3f546eda35168c3aa3cb91780fbe703f0996c1d133ea96dc85c70bbc0a", // 密钥,string 类型,必须是复杂密钥,长度大于16 - "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true - "ValidIssuer": "SimpleAdmin", // 签发方,string 类型 - "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true - "ValidAudience": "SimpleAdmin", // 签收方,string 类型 - "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true - "ExpiredTime": 50000, // 过期时间,long 类型,单位分钟,默认20分钟 - "ClockSkew": 10, // 过期时间容错值,long 类型,单位秒,默认5秒 - "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256 + "JwtSettings": { + "SecretKey": "YourSuperSecretKeyThatIsAtLeast32CharactersLong!", + "Issuer": "SimpleAdmin", + "Audience": "SimpleAdminClient", + "ExpiryInMinutes": 60, + "RefreshExpiryInDays": 7 }, "SignatureValidation": { "Enabled": true, // 是否启用签名验证 diff --git a/src/TrackCenter.Application/TrackCenter.Application.csproj b/src/TrackCenter.Application/TrackCenter.Application.csproj index ce6d89f6..5b26d3e5 100644 --- a/src/TrackCenter.Application/TrackCenter.Application.csproj +++ b/src/TrackCenter.Application/TrackCenter.Application.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/src/TrackCenter.Domain/TrackCenter.Domain.csproj b/src/TrackCenter.Domain/TrackCenter.Domain.csproj index 55d07e7e..82437846 100644 --- a/src/TrackCenter.Domain/TrackCenter.Domain.csproj +++ b/src/TrackCenter.Domain/TrackCenter.Domain.csproj @@ -9,11 +9,11 @@ - + - - + + diff --git a/src/TrackCenter.Domain/VEntities/VUserEntity.cs b/src/TrackCenter.Domain/VEntities/VUserEntity.cs index 3dea6c4b..7597a656 100644 --- a/src/TrackCenter.Domain/VEntities/VUserEntity.cs +++ b/src/TrackCenter.Domain/VEntities/VUserEntity.cs @@ -1,395 +1,64 @@ +using Fake.Domain.Entities.Auditing; + namespace TrackCenter.Domain.VEntities; /// -/// 服务商主表 +/// 用户视图实体 /// [SugarTable("v_user")] -public class VUserEntity +public class VUserEntity : FullAuditedAggregateRoot { /// - /// Desc:Id - /// Default: - /// Nullable:False + /// 主键 /// - [SugarColumn(IsPrimaryKey = true)] - public long Id { get; set; } + [SugarColumn(ColumnName = "Id", IsPrimaryKey = true)] + public Guid Id { get; set; } /// - /// Desc:头像 - /// Default: - /// Nullable:True + /// 用户名 /// - public string? Avatar { get; set; } + [SugarColumn(ColumnName = "Name")] + public string Name { get; set; } /// - /// Desc:签名 - /// Default: - /// Nullable:True + /// 账号 /// - public string? Signature { get; set; } + [SugarColumn(ColumnName = "Account")] + public string Account { get; set; } /// - /// Desc:账号 - /// Default: - /// Nullable:False + /// 加密密码 /// - public string Account { get; set; } = null!; + [SugarColumn(ColumnName = "EncryptPassword_Password")] + public string EncryptPasswordPassword { get; set; } /// - /// Desc:密码 - /// Default: - /// Nullable:False + /// 密码盐值 /// - public string Password { get; set; } = null!; + [SugarColumn(ColumnName = "EncryptPassword_Salt")] + public string EncryptPasswordSalt { get; set; } /// - /// Desc:姓名 - /// Default: - /// Nullable:True - /// - public string? Name { get; set; } - - /// - /// Desc:昵称 - /// Default: - /// Nullable:True - /// - public string? Nickname { get; set; } - - /// - /// Desc:性别 - /// Default: - /// Nullable:True - /// - public string? Gender { get; set; } - - /// - /// Desc:出生日期 - /// Default: - /// Nullable:True - /// - public string? Birthday { get; set; } - - /// - /// Desc:民族 - /// Default: - /// Nullable:True - /// - public string? Nation { get; set; } - - /// - /// Desc:籍贯 - /// Default: - /// Nullable:True - /// - public string? NativePlace { get; set; } - - /// - /// Desc:家庭住址 - /// Default: - /// Nullable:True - /// - public string? HomeAddress { get; set; } - - /// - /// Desc:通信地址 - /// Default: - /// Nullable:True - /// - public string? MailingAddress { get; set; } - - /// - /// Desc:证件类型 - /// Default: - /// Nullable:True - /// - public string? IdCardType { get; set; } - - /// - /// Desc:证件号码 - /// Default: - /// Nullable:True - /// - public string? IdCardNumber { get; set; } - - /// - /// Desc:文化程度 - /// Default: - /// Nullable:True - /// - public string? CultureLevel { get; set; } - - /// - /// Desc:政治面貌 - /// Default: - /// Nullable:True - /// - public string? PoliticalOutlook { get; set; } - - /// - /// Desc:毕业院校 - /// Default: - /// Nullable:True - /// - public string? College { get; set; } - - /// - /// Desc:学历 - /// Default: - /// Nullable:True - /// - public string? Education { get; set; } - - /// - /// Desc:学制 - /// Default: - /// Nullable:True - /// - public string? EduLength { get; set; } - - /// - /// Desc:学位 - /// Default: - /// Nullable:True - /// - public string? Degree { get; set; } - - /// - /// Desc:手机 - /// Default: - /// Nullable:True - /// - public string? Phone { get; set; } - - /// - /// Desc:邮箱 - /// Default: - /// Nullable:True + /// 邮箱 /// + [SugarColumn(ColumnName = "Email")] public string? Email { get; set; } /// - /// Desc:家庭电话 - /// Default: - /// Nullable:True + /// 头像 /// - public string? HomeTel { get; set; } + [SugarColumn(ColumnName = "Avatar")] + public string? Avatar { get; set; } /// - /// Desc:办公电话 - /// Default: - /// Nullable:True + /// 所属组织ID /// - public string? OfficeTel { get; set; } + [SugarColumn(ColumnName = "OrganizationId")] + public Guid? OrganizationId { get; set; } /// - /// Desc:紧急联系人 - /// Default: - /// Nullable:True + /// 用户ID(用于映射) /// - public string? EmergencyContact { get; set; } - - /// - /// Desc:紧急联系人电话 - /// Default: - /// Nullable:True - /// - public string? EmergencyPhone { get; set; } - - /// - /// Desc:紧急联系人地址 - /// Default: - /// Nullable:True - /// - public string? EmergencyAddress { get; set; } - - /// - /// Desc:员工编号 - /// Default: - /// Nullable:True - /// - public string? EmpNo { get; set; } - - /// - /// Desc:入职日期 - /// Default: - /// Nullable:True - /// - public string? EntryDate { get; set; } - - /// - /// Desc:机构id - /// Default: - /// Nullable:False - /// - public long OrgId { get; set; } - - /// - /// Desc:职位id - /// Default: - /// Nullable:False - /// - public long PositionId { get; set; } - - /// - /// Desc:职级 - /// Default: - /// Nullable:True - /// - public string? PositionLevel { get; set; } - - /// - /// Desc:主管id - /// Default: - /// Nullable:True - /// - public long? DirectorId { get; set; } - - /// - /// Desc:密码提醒修改时间 - /// Default: - /// Nullable:True - /// - public DateTime? PwdRemindUpdateTime { get; set; } - - /// - /// Desc:上次登录ip - /// Default: - /// Nullable:True - /// - public string? LastLoginIp { get; set; } - - /// - /// Desc:上次登录地点 - /// Default: - /// Nullable:True - /// - public string? LastLoginAddress { get; set; } - - /// - /// Desc:上次登录时间 - /// Default: - /// Nullable:True - /// - public DateTime? LastLoginTime { get; set; } - - /// - /// Desc:上次登录设备 - /// Default: - /// Nullable:True - /// - public string? LastLoginDevice { get; set; } - - /// - /// Desc:最新登录ip - /// Default: - /// Nullable:True - /// - public string? LatestLoginIp { get; set; } - - /// - /// Desc:最新登录地点 - /// Default: - /// Nullable:True - /// - public string? LatestLoginAddress { get; set; } - - /// - /// Desc:最新登录时间 - /// Default: - /// Nullable:True - /// - public DateTime? LatestLoginTime { get; set; } - - /// - /// Desc:最新登录设备 - /// Default: - /// Nullable:True - /// - public string? LatestLoginDevice { get; set; } - - /// - /// Desc:排序码 - /// Default: - /// Nullable:True - /// - public int? SortCode { get; set; } - - /// - /// Desc:默认模块 - /// Default: - /// Nullable:True - /// - public long? DefaultModule { get; set; } - - /// - /// Desc:状态 - /// Default:ENABLE - /// Nullable:True - /// - public string? Status { get; set; } - - /// - /// Desc:创建时间 - /// Default: - /// Nullable:True - /// - public DateTime? CreateTime { get; set; } - - /// - /// Desc:更新时间 - /// Default: - /// Nullable:True - /// - public DateTime? UpdateTime { get; set; } - - /// - /// Desc:创建者Id - /// Default: - /// Nullable:True - /// - public long? CreateUserId { get; set; } - - /// - /// Desc:修改者Id - /// Default: - /// Nullable:True - /// - public long? UpdateUserId { get; set; } - - /// - /// Desc:创建人 - /// Default: - /// Nullable:True - /// - public string? CreateUser { get; set; } - - /// - /// Desc:更新人 - /// Default: - /// Nullable:True - /// - public string? UpdateUser { get; set; } - - /// - /// Desc:软删除 - /// Default:true - /// Nullable:True - /// - public bool? IsDelete { get; set; } - - /// - /// Desc:扩展信息 - /// Default: - /// Nullable:True - /// - public string? ExtJson { get; set; } - - /// - /// Desc:用户id(特意映射) - /// Default: - /// Nullable:False - /// - [SugarColumn(IsIdentity = true)] + [SugarColumn(ColumnName = "UserId", IsIdentity = true)] public int UserId { get; set; } } diff --git a/src/TrackCenter.Repository/Repositories/TrackContentRepository.cs b/src/TrackCenter.Repository/Repositories/TrackContentRepository.cs index def738f1..affc45a4 100644 --- a/src/TrackCenter.Repository/Repositories/TrackContentRepository.cs +++ b/src/TrackCenter.Repository/Repositories/TrackContentRepository.cs @@ -54,8 +54,8 @@ public class TrackContentRepository : BasicRepository, ITrac { var pagedList = await Context.Queryable() .LeftJoin((a, b) => a.TrackStatusId == b.Id && b.IsDeleted == false) - .LeftJoin((a, b, e) => a.CreateUserId == e.UserId && e.IsDelete == false) - .LeftJoin((a, b, e, f) => a.UpdateUserId == f.UserId && f.IsDelete == false) + .LeftJoin((a, b, e) => a.CreateUserId == e.UserId && e.IsDeleted == false) + .LeftJoin((a, b, e, f) => a.UpdateUserId == f.UserId && f.IsDeleted == false) .WhereIF(!input.AppKey.IsNullOrWhiteSpace(), (a, b, e, f) => a.AppKey == input.AppKey) .WhereIF(!input.Keywords.IsNullOrWhiteSpace(), (a, b, e, f) => a.Code.Contains(input.Keywords!) || a.Content.Contains(input.Keywords!) diff --git a/src/TrackCenter.Repository/Repositories/TrackFlagRepository.cs b/src/TrackCenter.Repository/Repositories/TrackFlagRepository.cs index b27d5614..72f8b51b 100644 --- a/src/TrackCenter.Repository/Repositories/TrackFlagRepository.cs +++ b/src/TrackCenter.Repository/Repositories/TrackFlagRepository.cs @@ -39,8 +39,8 @@ public class TrackFlagRepository : BasicRepository, ITrackFlagR PagedResult pagedList = new PagedResult(); pagedList = await Context.Queryable() .LeftJoin((a, b) => a.AppKey == b.AppKey && b.IsDeleted == false) - .LeftJoin((a, b, c) => a.CreateUserId == c.UserId && c.IsDelete == false) - .LeftJoin((a, b, c, d) => a.UpdateUserId == d.UserId && d.IsDelete == false) + .LeftJoin((a, b, c) => a.CreateUserId == c.UserId && c.IsDeleted == false) + .LeftJoin((a, b, c, d) => a.UpdateUserId == d.UserId && d.IsDeleted == false) .WhereIF(!input.AppKey.IsNullOrWhiteSpace(), (a, b, c, d) => a.AppKey == input.AppKey) .WhereIF(!input.Keywords.IsNullOrWhiteSpace(), (a, b, c, d) => SqlFunc.Contains(a.Code, input.Keywords)) .OrderByIF(input.SelectIds.IsNullOrEmpty(), (a, b, c, d) => a.CreateTime, OrderByType.Desc) diff --git a/src/TrackCenter.Repository/Repositories/TrackStatusRepository.cs b/src/TrackCenter.Repository/Repositories/TrackStatusRepository.cs index 7d5c227a..f629dbd9 100644 --- a/src/TrackCenter.Repository/Repositories/TrackStatusRepository.cs +++ b/src/TrackCenter.Repository/Repositories/TrackStatusRepository.cs @@ -37,8 +37,8 @@ public class TrackStatusRepository : BasicRepository, ITrackS public async Task> GetPageTrackStatus(GetPagedTrackStatusVO input) { var pagedList = await Context.Queryable() - .LeftJoin((a, b) => a.CreateUserId == b.UserId && b.IsDelete == false) - .LeftJoin((a, b, d) => a.UpdateUserId == d.UserId && d.IsDelete == false) + .LeftJoin((a, b) => a.CreateUserId == b.UserId && b.IsDeleted == false) + .LeftJoin((a, b, d) => a.UpdateUserId == d.UserId && d.IsDeleted == false) .WhereIF(!input.AppKey.IsNullOrWhiteSpace(), (a, b, d) => a.AppKey == input.AppKey) .WhereIF(!input.Keywords.IsNullOrWhiteSpace(), (a, b, d) => a.Status.Contains(input.Keywords!) || a.EnStatus.Contains(input.Keywords!) ||