为ABP新增手机验证模块

news/2024/11/7 14:36:47/

当前手机验证基本是标配,但Abp自身并没有实现这个功能,于是有了通过自定义模块实现的想法。

经过研究,发现要实现这个,只要重写和替换包含ReplaceEmailToUsernameOfInputIfNeeds方法的类就可以了。但要实现这个,首先要在IdentityUserManager类中添加FindByPhoneAsync方法用来通过手机号码查询用户。刚开始想通过扩展方法的方式来实现,但发现唯一能用来获取用户集合的公共属性Users并不能用,而又没有其他办法获取存储,于是放弃该方法。现在只能通过自定义IdentityUserManager来实现了。于是在创建了Generic.Abp.PhoneLogin.Domain模块定义了PhoneLoginUserManager对象。

Abp的源代码中搜索ReplaceEmailToUsernameOfInputIfNeeds,会发现有以下5个类包含该方法:

  • Volo.Abp.Account.Web模块的AccountControllerLoginModel
  • Volo.Abp.Account.Web.IdentityServer模块的IdentityServerSupportedLoginModel
  • Volo.Abp.IdentityServer.Domain模块的AbpResourceOwnerPasswordValidator
  • Volo.Abp.OpenIddict.AspNetCore模块的TokenController

Volo.Abp.Account.Web模块的AccountControllerLoginModel

由于Volo.Abp.Account.Web.IdentityServer模块的IdentityServerSupportedLoginModel调用的是Volo.Abp.Account.Web模块的``LoginModelReplaceEmailToUsernameOfInputIfNeeds`方法,因而可以忽悠这个。

对应各个要重写的模块,建立对应的模块就行了。
对于AccountController,通过替换控制器的方式就可实现替换了,具体代码如下:

    [IgnoreAntiforgeryToken][RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)][Controller][ControllerName("Login")][Area("account")][Route("api/account")][Dependency(ReplaceServices = true)][ExposeServices(typeof(AccountController), IncludeSelf = true)]public class PhoneLoginAccountController : AccountController{public PhoneLoginAccountController(SignInManager<IdentityUser> signInManager,PhoneLoginUserManager userManager,ISettingProvider settingProvider,IdentitySecurityLogManager identitySecurityLogManager,IOptions<IdentityOptions> identityOptions) :base(signInManager, userManager, settingProvider, identitySecurityLogManager, identityOptions){LocalizationResource = typeof(AccountResource);PhoneLoginUserManager = userManager;}protected PhoneLoginUserManager PhoneLoginUserManager { get; }protected override async Task ReplaceEmailToUsernameOfInputIfNeeds(UserLoginInfo login){var userByUsername = await UserManager.FindByNameAsync(login.UserNameOrEmailAddress);if (userByUsername != null){return;}var userByPhone = await PhoneLoginUserManager.FindByPhoneAsync(login.UserNameOrEmailAddress);if (userByPhone != null){login.UserNameOrEmailAddress = userByPhone.UserName;return;}if (!ValidationHelper.IsValidEmailAddress(login.UserNameOrEmailAddress)){return;}var userByEmail = await UserManager.FindByEmailAsync(login.UserNameOrEmailAddress);if (userByEmail != null){login.UserNameOrEmailAddress = userByEmail.UserName;return;}return;}}

ReplaceEmailToUsernameOfInputIfNeeds方法内,主要是通过FindByPhoneAsync方法查找用户,如果找到用户,就用找到的用户名替换登录用户名就行了。

在这里要注意的是使用PhoneLoginUserManager替换原来的IdentityUserManager

对于LoginModel,可以使用只替换LoginModel的方式,这里图方便直接使用了覆盖Login.cshtml的方式。代码就不贴了,大家可以去Github查看源代码。

Volo.Abp.IdentityServer.Domain模块的AbpResourceOwnerPasswordValidator

IdentityServer4是通过IResourceOwnerPasswordValidator接口来实现密码验证的,因而要替换IResourceOwnerPasswordValidator需要点技巧,笔者也是找了一圈才找到的。

具体的ReplaceEmailToUsernameOfInputIfNeeds方法就不贴了,基本上和AccountController没什么不同。

最难部分是在模块定义中替换原有的AbpResourceOwnerPasswordValidator:

    public class GenericAbpPhoneLoginIdentityServerDomainModule : AbpModule{public override void PreConfigureServices(ServiceConfigurationContext context){PreConfigure<IIdentityServerBuilder>(builder =>{builder.AddResourceOwnerValidator<PhoneLoginResourceOwnerPasswordValidator>();});context.Services.Replace(ServiceDescriptor.Transient<AbpResourceOwnerPasswordValidator, PhoneLoginResourceOwnerPasswordValidator>());}}

代码需要先把PhoneLoginResourceOwnerPasswordValidator添加到验证器,然后再替换。

Volo.Abp.OpenIddict.AspNetCore模块的TokenController

这个和替换AccountController没什么不同,就不具体说了。

使用方法

OpenIddict

  • 在应用的Domain.Shared模块引用Generic.Abp.PhoneLogin.Domain.Shared
  • 在应用的Domain模块引用Generic.Abp.PhoneLogin.Domain
  • 在应用的Web模块引用Generic.Abp.PhoneLogin.Account.WebGeneric.Abp.PhoneLogin.OpenIddict.AspNetCore

IdenttityServer

  • 在应用的Domain.Shared模块引用Generic.Abp.PhoneLogin.Domain.Shared
  • 在应用的Domain模块引用Generic.Abp.PhoneLogin.DomainGeneric.Abp.PhoneLogin.IdentityServer.Domain
  • 在应用的Web模块引用Generic.Abp.PhoneLogin.Account.Web

具体示例可查看分支测试identtiyServer4手机登录

验证获取令牌
源代码:https://github.com/tianxiaode/GenericAbp


http://www.ppmy.cn/news/11488.html

相关文章

【BZOJ4916】神犇与蒟蒻

题目大意 很久很久以前&#xff0c;有一只神犇叫yzy; 很久很久之后&#xff0c;有一只蒟蒻叫lty; 输入一个整数nnn&#xff0c;1≤n≤1091\leq n\leq 10^91≤n≤109 请你输出一个整数A∑i1nμ(i2)A\sum\limits_{i1}^n\mu(i^2)Ai1∑n​μ(i2) 请你输出一个整数B∑i1nϕ(i2)B\s…

CentOS7下Nginx安装

安装nginx的基本环境部署 1、gcc、 gcc-c 是用来编译下载下来的nginx源码 2、pcre和pcre-devel PCRE(Perl Compatible Regular Expressions) 是一个Perl库&#xff0c;包括 perl 兼容的正则表达式库。 nginx 的 http 模块使用 pcre 来解析正则表达式&#xff0c;pcre-devel 是…

Qt扫盲-Qt QObject模型概述

Qt QObject模型概述一、概述二、 Qt Object Model 类三、Qt对象: Identities vs Value一、概述 标准的c对象模型为对象范式提供了非常高效的运行时支持。但它的静态特性在某些问题领域是不灵活的。图形用户界面编程是一个既需要运行时效率又需要高度灵活性的领域。Qt通过结合c…

java mybatis的SpringBoot博客论坛管理系统

java mybatis的SpringBoot博客论坛管理系统 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式…

通讯录的实现(详解)(后附完整源代码)

通讯录的实现一.所需要的功能二.大致菜单三.创建通讯录四.增加联系人五.显示联系人六.查找联系人七.删除联系人八.修改联系人九.按名字排序一.所需要的功能 对于通讯录来说&#xff0c;我们需要它实现以下几个功能。 1.人的信息&#xff1a;姓名年龄性别电话地址。 2.可以存放…

【Linux】信号机制(非实时信号)

目录 前言 一.信号的概念以及产生 1.什么是信号 2.信号分为两类 3.查看信号的命令 4.信号如何产生 1).通过软件产生 2).通过硬件产生 3).通过键盘组合键产生 二.信号的发送以及保存 1.信号如何发送 2.信号如何保存 1).概念 2).底层实现结构&&内核中的实现…

微服务自动化管理【docker compose】

1.什么是docker-compose Docker-Compose项目是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排 通过编写docker-compose文件可对多个服务同时进行启动/停止/更新(可定义依赖&#xff0c;按顺序启动服务) docker-compose将所管理的容器分为3层结构&#…

连接查询入门

1、什么是连接查询&#xff1f; 从一张表中查询数据&#xff0c;称为单表查询。 多张表联合起来查询数据&#xff0c;称为连接查询。在实际开发中一般一个业务会对应多张表,所以连接查询使用较多。 2、连接查询的分类&#xff1a; 根据语法的年代分类&#xff1a;SQL92(1992年出…