• abp vnext 通过Claim扩展用户表字段


    需求:abp框架原有的abpusers表字段无法满足业务需求,需要新增字段来解决。

    实现步骤如下

    一.向abpusres表添加字段

    1、在domain程序集下新建AppUser表

    该类用来定义新增的字段,不需要继承任何父类,如下所示:

    1. public class AppUser
    2. {
    3. ///
    4. /// 会员Code
    5. ///
    6. [MaxLength(50)]
    7. public string MemberCode { get; set; }
    8. }

    2.在EntityFrameworkCore程序集添加MyAppEfCoreEntityExtensionMappings类,

    类名可以随意,但是按照惯例,一般以“项目名”+EfCoreEntityExtensionMappings命名。该类主要用来配置为IdentityUser新增字段,代码如下:

    1. public class DemoEfCoreEntityExtensionMappings
    2. {
    3. private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
    4. public static void Configure()
    5. {
    6. OneTimeRunner.Run(() =>
    7. {
    8. ObjectExtensionManager.Instance.MapEfCorePropertystring>(nameof(AppUser.MemberCode), b => { b.HasMaxLength(50); });
    9. });
    10. }
    11. }

    3.在DemoEntityFrameworkCore程序集下的DemoEntityFrameworkCoreModule模块中配置PreConfigureServices

    1. public override void PreConfigureServices(ServiceConfigurationContext context)
    2. {
    3. DemoEfCoreEntityExtensionMappings.Configure();
    4. base.PreConfigureServices(context);
    5. }

    4.在Admin.HttpApi.Host程序集配置AdminHttpApiHostMigrationsDbContextFactory类中的CreateDbContext

    同上一步,在DbContextFactory中进行同样配置,一些情况下我们需要通过DbContextFactory来获取DbContext,如不配置此项,将会导致获取的DbContext中内容不一致。

    1. public DemoDbContext CreateDbContext(string[] args)
    2. {
    3. var configuration = BuildConfiguration();
    4. var builder = new DbContextOptionsBuilder()
    5. .UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion,
    6. option => { option.MigrationsAssembly("Demo.Admin.HttpApi.Host"); });
    7. //添加扩展配置
    8. DemoEfCoreEntityExtensionMappings.Configure();
    9. return new DemoDbContext(builder.Options);
    10. }

    5.在Application.Contracts层配置用户表相关Dto的扩展字段

    1. public static class DemoDtoExtensions
    2. {
    3. private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
    4. public static void Configure()
    5. {
    6. OneTimeRunner.Run(() =>
    7. {
    8. ObjectExtensionManager.Instance
    9. .AddOrUpdateProperty<string>(
    10. new[]
    11. {
    12. typeof(IdentityUserDto),
    13. typeof(IdentityUserCreateDto),
    14. typeof(IdentityUserUpdateDto),
    15. typeof(ProfileDto),
    16. typeof(UpdateProfileDto)
    17. },
    18. "MemberCode"
    19. );
    20. });
    21. }
    22. }

    6、在模块类ApplicationContractsModule中进行配置

    为了是上一步配置生效,还需要在MyAppApplicationContractsModule中进行如下配置:

    1. public override void PreConfigureServices(ServiceConfigurationContext context)
    2. {
    3. DemoDtoExtensions.Configure();
    4. base.PreConfigureServices(context);
    5. }

    7、通过EF Core将MemberCode字段添加到abpUsers表中

         1)生成迁移脚本

               add-migration   add_abpUusers_MemberCode

         2)  将迁移脚本sql更新到数据库

              update-database

    二.向CurrentUser会话中Claim赋值

    1.在Admin.HttpApi程序集下LoginController类中给toekn中Claim添加自定义字段

    1. ///
    2. /// 在CurrentUser对象的Claims中添加扩展字段
    3. ///
    4. private List SetUserClaims(IdentityUser userInfo)
    5. {
    6. List claims = new List();
    7. if (userInfo.ExtraProperties.ContainsKey("MemberCode"))
    8. {
    9. //添加会员Code
    10. claims.Add(new Claim(MemberCode,userInfo.ExtraProperties["MemberCode"].ToString()));
    11. }
    12. return claims;
    13. }
    14. //在abp框架生成的方法中添加
    15. private async Task<string> GetToken(IdentityUser user, string[] roles)
    16. {
    17. var claims = await CreateJwtClaims(user, roles);
    18. //添加自定义claim
    19. List customClaims = SetUserClaims(userInfo);
    20. if (!customClaims.IsNullOrEmpty())
    21. {
    22. claims.AddRange(customClaims);
    23. }
    24. //...
    25. }

    2.在程序集中使用

    1. //获取abpuser表中扩展字段MemberCode值
    2. var storeCode = CurrentUser.FindClaimValue("MemberCode");

    三、前端账号管理添加扩展字段

    1.账号管理列表 

    1. //修改vben-admin\src\views\identity\user\datas\TableData.ts列表参数配置
    2. {
    3. title: '会员Code',
    4. dataIndex: 'extraProperties.MemberCode',
    5. align: 'left',
    6. width: 270,
    7. sorter: true,
    8. slots: { customRender: 'MemberCode' }, //通过自定义插槽在列表中显示
    9. },
    1. //(修改vben-admin\src\views\identity\user\components\UserTable.vue列表参数配置)
    2. <BasicTable @register="registerTable">
    3. <template #MemberCode="{ record }">
    4. {{ record.extraProperties.MemberCode}}
    5. template>
    6. BasicTable>

    2.修改列表添加扩展字段

    1. //修改vben-admin\src\views\identity\user\datas\ModalData.ts配置
    2. {
    3. tab: t('AbpIdentity.UserInformations'),
    4. field: 'memberCode',
    5. component: 'Input',
    6. label: '会员Code',
    7. colProps: { span: 24 },
    8. },

    1. //在弹框打开事件里,通过useForm回调函数setFieldsValue设置会员code值
    2. const [registerModal, { closeModal }] = useModalInner(async (val) => {
    3. const formEl = unref(formElRef);
    4. formEl?.setFieldsValue({
    5. memberCode: val.extraProperties.MemberCode,
    6. });
    7. });
    8. //保存时需要将会员Code值按后台api接口存在
    9. handleSubmit() {
    10. const formEl = unref(this.formElRef);
    11. const param = formEl?.getFieldsValue();
    12. if (param) {
    13. param.extraProperties = { MemberCode: param.MemberCode};
    14. }
    15. formEl?.validate().then(() => {
    16. this.handleSaveUser(param).then(() => {
    17. this.$emit('change');
    18. this.closeModal();
    19. });
    20. });
    21. },

    注:表单组件对JSON数据格式读取只能读取一层,像val.extraProperties.MemberCode是读取不到的,需要转换一下。

    保存的时候格式又要转回去,必须和接口数据保持一致才行

  • 相关阅读:
    通过S2B2C供应链电商平台网站解决方案,实现大宗商品万亿产业数字化转型
    生产设备上的静电该如何处理?
    数据挖掘 决策树
    动态内存管理(C语言)
    (JavaEE) 多线程基础3——多线程的代码案例 (单例模式, 阻塞队列,定时器)详解!!!
    uniapp 开发H5判断当前是否是微信浏览器
    Unix信号处理
    Adobe推出AI视频超分辨率工具VideoGigaGAN
    java反射机制详解
    GitLab CI/CD的原理及应用详解(三)
  • 原文地址:https://blog.csdn.net/hezheqiang/article/details/125718273