瀏覽代碼

新增 实现标准标识密码哈希新增appconfig.json.passwordHasher配置,方便导入abp用户密码数据也可正常登录
新增 实现swagger.json枚举类选项为枚举属性名新增appconfig.json.swagger.enableJsonStringEnumConverter配置

zhontai 2 年之前
父節點
當前提交
bfc72c8e61

+ 6 - 2
src/hosts/ZhonTai.Host/Configs/appconfig.json

@@ -4,7 +4,7 @@
   //Api地址
   "urls": [ "http://*:8000" ],
   //跨域地址
-  "corUrls": [ ],
+  "corUrls": [],
   //程序集名称
   "assemblyNames": [ "ZhonTai.Admin" ],
   //租户
@@ -26,6 +26,8 @@
     "enableEnumSchemaFilter": true,
     //启用接口排序文档过滤器
     "enableOrderTagsDocumentFilter": true,
+    //启用枚举属性名
+    "enableJsonStringEnumConverter": true,
     //路由前缀,如配置微服务文档地址:doc/module/swagger
     "routePrefix": "swagger",
     //地址
@@ -89,5 +91,7 @@
   "dynamicApi": {
     //结果格式化
     "formatResult": true
-  }
+  },
+  //实现标准标识密码哈希
+  "passwordHasher": true
 }

+ 6 - 0
src/hosts/ZhonTai.Host/Program.cs

@@ -41,6 +41,12 @@ new HostApp(new HostAppOptions
 
         context.Services.AddOSS();
     },
+
+    //配置mvc
+    ConfigureMvcBuilder = (mvcBuilder, options) =>
+    {
+    },
+
 	//配置后置中间件
 	ConfigurePostMiddleware = context =>
     {

+ 10 - 0
src/platform/ZhonTai.Admin/Core/Configs/AppConfig.cs

@@ -89,6 +89,11 @@ public class AppConfig
     /// 动态Api配置
     /// </summary>
     public DynamicApiConfig DynamicApi { get; set; } = new DynamicApiConfig();
+
+    /// <summary>
+    /// 实现标准标识密码哈希
+    /// </summary>
+    public bool PasswordHasher { get; set; } = false;
 }
 
 /// <summary>
@@ -111,6 +116,11 @@ public class SwaggerConfig
     /// </summary>
     public bool EnableOrderTagsDocumentFilter { get; set; } = true;
 
+    /// <summary>
+    /// 启用枚举属性名
+    /// </summary>
+    public bool EnableJsonStringEnumConverter { get; set; } = false;
+
     private string _RoutePrefix = "swagger";
     /// <summary>
     /// 访问地址

+ 3 - 3
src/platform/ZhonTai.Admin/Core/Filters/EnumSchemaFilter.cs

@@ -1,4 +1,5 @@
-using Microsoft.OpenApi.Models;
+using FreeSql.Internal;
+using Microsoft.OpenApi.Models;
 using Swashbuckle.AspNetCore.SwaggerGen;
 using System;
 using System.Linq;
@@ -19,7 +20,7 @@ public class EnumSchemaFilter : ISchemaFilter
             var enumValueType = type.GetField("value__").FieldType;
             var items = Enum.GetValues(type).Cast<Enum>()
             .Where(m => !m.ToString().Equals("Null")).Select(x =>
-            $"{x.ToDescription()}={Convert.ChangeType(x, enumValueType)}").ToList();
+            $"{x.ToNameWithDescription()}={Convert.ChangeType(x, enumValueType)}").ToList();
 
             if (items?.Count > 0)
             {
@@ -29,7 +30,6 @@ public class EnumSchemaFilter : ISchemaFilter
                 //    ["description"] = new OpenApiString(description)
                 //});
                 //CommonUtils.GetProperyCommentBySummary
-
                 schema.Description = string.IsNullOrEmpty(schema.Description) ? description : $"{schema.Description}:{description}";
             }
         }

+ 6 - 0
src/platform/ZhonTai.Admin/Core/HostApp.cs

@@ -53,6 +53,8 @@ using ZhonTai.Admin.Core.Dto;
 using ZhonTai.DynamicApi.Attributes;
 using System.Text.RegularExpressions;
 using Swashbuckle.AspNetCore.SwaggerGen;
+using Newtonsoft.Json.Converters;
+using System.Text.Json.Serialization;
 
 namespace ZhonTai.Admin.Core;
 
@@ -535,6 +537,10 @@ public class HostApp
         })
         .AddControllersAsServices();
 
+        if (appConfig.Swagger.EnableJsonStringEnumConverter)
+            mvcBuilder.AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
+
+        _hostAppOptions?.ConfigureMvcBuilder?.Invoke(mvcBuilder, hostAppContext);
         #endregion 控制器
 
         services.AddHttpClient();

+ 4 - 0
src/platform/ZhonTai.Admin/Core/RegisterModules/RegisterModule.cs

@@ -10,6 +10,7 @@ using ZhonTai.Admin.Core.Configs;
 using ZhonTai.Admin.Core.Db.Transaction;
 using ZhonTai.Admin.Core.Attributes;
 using ZhonTai.Admin.Core.Repositories;
+using Microsoft.AspNetCore.Identity;
 
 namespace ZhonTai.Admin.Core.RegisterModules;
 
@@ -68,6 +69,9 @@ public class RegisterModule : Module
             .InterceptedBy(interceptorServiceTypes.ToArray())
             .EnableClassInterceptors();
 
+            if(_appConfig.PasswordHasher)
+                builder.RegisterGeneric(typeof(PasswordHasher<>)).As(typeof(IPasswordHasher<>)).SingleInstance().PropertiesAutowired();
+
             //仓储泛型注入
             builder.RegisterGeneric(typeof(RepositoryBase<>)).As(typeof(IRepositoryBase<>)).InstancePerLifetimeScope().PropertiesAutowired();
             builder.RegisterGeneric(typeof(RepositoryBase<,>)).As(typeof(IRepositoryBase<,>)).InstancePerLifetimeScope().PropertiesAutowired();

+ 6 - 0
src/platform/ZhonTai.Admin/Core/Startup/HostAppOptions.cs

@@ -1,4 +1,5 @@
 using FreeSql;
+using Microsoft.Extensions.DependencyInjection;
 using System;
 using Yitter.IdGenerator;
 using ZhonTai.DynamicApi;
@@ -25,6 +26,11 @@ public class HostAppOptions
     /// </summary>
     public Action<HostAppContext> ConfigurePostServices { get; set; }
 
+    /// <summary>
+    /// 注入后置服务
+    /// </summary>
+    public Action<IMvcBuilder, HostAppContext> ConfigureMvcBuilder { get; set; }
+
     /// <summary>
     /// 注入前置中间件
     /// </summary>

+ 6 - 1
src/platform/ZhonTai.Admin/Domain/UserStaff/Sex.cs

@@ -1,4 +1,6 @@
-namespace ZhonTai.Admin.Domain.UserStaff;
+using System.ComponentModel;
+
+namespace ZhonTai.Admin.Domain.UserStaff;
 
 /// <summary>
 /// 性别
@@ -8,15 +10,18 @@ public enum Sex
     /// <summary>
     /// 未知
     /// </summary>
+    [Description("未知")]
     Unknown = 0,
 
     /// <summary>
     /// 男
     /// </summary>
+    [Description("男")]
     Male = 1,
 
     /// <summary>
     /// 女
     /// </summary>
+    [Description("女")]
     Female = 2
 }

+ 18 - 4
src/platform/ZhonTai.Admin/Services/Auth/AuthService.cs

@@ -31,6 +31,7 @@ using ZhonTai.DynamicApi;
 using ZhonTai.DynamicApi.Attributes;
 using FreeSql;
 using ZhonTai.Admin.Domain.TenantPermission;
+using Microsoft.AspNetCore.Identity;
 
 namespace ZhonTai.Admin.Services.Auth;
 
@@ -46,6 +47,7 @@ public class AuthService : BaseService, IAuthService, IDynamicApi
     private readonly IUserRepository _userRepository;
     private readonly ITenantRepository _tenantRepository;
     private readonly ICaptchaTool _captchaTool;
+    private IPasswordHasher<UserEntity> _passwordHasher => LazyGetRequiredService<IPasswordHasher<UserEntity>>();
 
     public AuthService(
         AppConfig appConfig,
@@ -236,10 +238,22 @@ public class AuthService : BaseService, IAuthService, IDynamicApi
             #endregion
 
             #region 登录
-            var password = MD5Encrypt.Encrypt32(input.Password);
-            var user = await _userRepository.Select.Where(a => a.UserName == input.UserName && a.Password == password).ToOneAsync();
-
-            if (!(user?.Id > 0))
+            var user = await _userRepository.Select.Where(a => a.UserName == input.UserName).ToOneAsync();
+            var valid = user?.Id > 0;
+            if(valid)
+            {
+                if (_appConfig.PasswordHasher)
+                {
+                    var passwordVerificationResult = _passwordHasher.VerifyHashedPassword(user, user.Password, input.Password);
+                    valid = passwordVerificationResult == PasswordVerificationResult.Success || passwordVerificationResult == PasswordVerificationResult.SuccessRehashNeeded;
+                }
+                else
+                {
+                    var password = MD5Encrypt.Encrypt32(input.Password);
+                    valid = user.Password == password;
+                }
+            }
+            if (!valid)
             {
                 throw ResultOutput.Exception("用户名或密码错误");
             }

+ 19 - 3
src/platform/ZhonTai.Admin/Services/User/UserService.cs

@@ -29,6 +29,7 @@ using FreeSql;
 using ZhonTai.Admin.Domain.User.Dto;
 using ZhonTai.Admin.Domain.RoleOrg;
 using ZhonTai.Admin.Domain.UserOrg;
+using Microsoft.AspNetCore.Identity;
 
 namespace ZhonTai.Admin.Services.User;
 
@@ -49,6 +50,8 @@ public partial class UserService : BaseService, IUserService, IDynamicApi
     private IRoleOrgRepository _roleOrgRepository => LazyGetRequiredService<IRoleOrgRepository>();
     private IUserOrgRepository _userOrgRepository => LazyGetRequiredService<IUserOrgRepository>();
 
+    private IPasswordHasher<UserEntity> _passwordHasher => LazyGetRequiredService<IPasswordHasher<UserEntity>>();
+
     public UserService()
     {
     }
@@ -315,10 +318,16 @@ public partial class UserService : BaseService, IUserService, IDynamicApi
             input.Password = _appConfig.DefaultPassword;
         }
 
-        input.Password = MD5Encrypt.Encrypt32(input.Password);
-
         var entity = Mapper.Map<UserEntity>(input);
         entity.Type = UserType.DefaultUser;
+        if (_appConfig.PasswordHasher)
+        {
+            entity.Password = _passwordHasher.HashPassword(entity, input.Password);
+        }
+        else
+        {
+            entity.Password = MD5Encrypt.Encrypt32(input.Password);
+        }
         var user = await _userRepository.InsertAsync(entity);
         var userId = user.Id;
 
@@ -552,7 +561,14 @@ public partial class UserService : BaseService, IUserService, IDynamicApi
         {
             password = "111111";
         }
-        entity.Password = MD5Encrypt.Encrypt32(password);
+        if (_appConfig.PasswordHasher)
+        {
+            entity.Password = _passwordHasher.HashPassword(entity, input.Password);
+        }
+        else
+        {
+            entity.Password = MD5Encrypt.Encrypt32(input.Password);
+        }
         await _userRepository.UpdateAsync(entity);
         return password;
     }

+ 15 - 0
src/platform/ZhonTai.Admin/ZhonTai.Admin.xml

@@ -371,6 +371,11 @@
             动态Api配置
             </summary>
         </member>
+        <member name="P:ZhonTai.Admin.Core.Configs.AppConfig.PasswordHasher">
+            <summary>
+            实现标准标识密码哈希
+            </summary>
+        </member>
         <member name="T:ZhonTai.Admin.Core.Configs.SwaggerConfig">
             <summary>
             Swagger配置
@@ -391,6 +396,11 @@
             启用接口排序文档过滤器
             </summary>
         </member>
+        <member name="P:ZhonTai.Admin.Core.Configs.SwaggerConfig.EnableJsonStringEnumConverter">
+            <summary>
+            启用枚举属性名
+            </summary>
+        </member>
         <member name="P:ZhonTai.Admin.Core.Configs.SwaggerConfig.RoutePrefix">
             <summary>
             访问地址
@@ -1916,6 +1926,11 @@
             注入后置服务
             </summary>
         </member>
+        <member name="P:ZhonTai.Admin.Core.Startup.HostAppOptions.ConfigureMvcBuilder">
+            <summary>
+            注入后置服务
+            </summary>
+        </member>
         <member name="P:ZhonTai.Admin.Core.Startup.HostAppOptions.ConfigurePreMiddleware">
             <summary>
             注入前置中间件

+ 7 - 0
src/platform/ZhonTai.Common/Extensions/EnumExtension.cs

@@ -15,6 +15,13 @@ public static class EnumExtension
         return desc?.Description ?? name;
     }
 
+    public static string ToNameWithDescription(this Enum item)
+    {
+        string name = item.ToString();
+        var desc = item.GetType().GetField(name)?.GetCustomAttribute<DescriptionAttribute>();
+        return $"name{(desc != null && desc.Description.IsNull() ? "" : $"({desc?.Description})")}";
+    }
+
     public static long ToInt64(this Enum item)
     {
         return Convert.ToInt64(item);