首页 > 其他分享 >Abp.Zero 手机号免密登录验证与号码绑定功能的实现(二):改造Abp默认实现

Abp.Zero 手机号免密登录验证与号码绑定功能的实现(二):改造Abp默认实现

时间:2022-11-01 18:26:16浏览次数:78  
标签:免密 return string await Abp Zero Task user public

接下来我们重写原Abp的部分实现,来驳接手机号相关业务。

改造User类

重写PhoneNumber使得电话号码为必填项,和中国大陆手机号11位长度

public new const int MaxPhoneNumberLength = 11;

[Required]
[StringLength(MaxPhoneNumberLength)]
public override string PhoneNumber { get; set; }


改造UserStore类

扩展通过PhoneNumber查找用户的方法


public async Task<User> FindByNameOrPhoneNumberAsync(string userNameOrPhoneNumber)
{

    return await UserRepository.FirstOrDefaultAsync(
        user => user.NormalizedUserName == userNameOrPhoneNumber || user.PhoneNumber == userNameOrPhoneNumber
    );
}

[UnitOfWork]
public async Task<User> FindByNameOrPhoneNumberAsync(int? tenantId, string userNameOrPhoneNumber)
{
    using (_unitOfWorkManager.Current.SetTenantId(tenantId))
    {
        return await FindByNameOrPhoneNumberAsync(userNameOrPhoneNumber);
    }
}

改造UserManager类

添加检测重复电话号码的方法CheckDuplicateUsernameOrPhoneNumber


public async Task<IdentityResult> CheckDuplicateUsernameOrPhoneNumber(long? expectedUserId, string userName, string phone)
{
    var user = await FindByNameAsync(userName);
    if (user != null && user.Id != expectedUserId)
    {
        throw new UserFriendlyException(string.Format(L("Identity.DuplicateUserName"), userName));
    }

    user = await FindByNameOrPhoneNumberAsync(GetCurrentTenantId(), phone);
    if (user != null && user.Id != expectedUserId)
    {
        throw new UserFriendlyException("电话号码重复", phone);
    }

    return IdentityResult.Success;
}

重写对用户的Create和Update,使其先检测是否重复电话号码。

//override

public override async Task<IdentityResult> CreateAsync(User user)
{
    var result = await CheckDuplicateUsernameOrPhoneNumber(user.Id, user.UserName, user.PhoneNumber);
    if (!result.Succeeded)
    {
        return result;
    }


    return await base.CreateAsync(user);
}

public override async Task<IdentityResult> UpdateAsync(User user)
{
    var result = await CheckDuplicateUsernameOrPhoneNumber(user.Id, user.UserName, user.PhoneNumber);
    if (!result.Succeeded)
    {
        return result;
    }

    return await base.UpdateAsync(user);
}

改造LogInManager类

分别重写LoginAsyncInternal,TryLoginFromExternalAuthenticationSourcesAsync两个方法,在用Email找不到用户之后,添加用手机号码查找用户的逻辑,添加的代码如下:

...
if (user == null)
{
    user = await userManager.FindByNameOrPhoneNumberAsync(tenantId, combinationName);
}

编写验证源

新建电话号码验证源类PhoneNumberExternalAuthenticationSource,并实现验证码校验逻辑,具体的代码

public class PhoneNumberExternalAuthenticationSource : DefaultExternalAuthenticationSource<Tenant, User>, ITransientDependency
{
    private readonly CaptchaManager captchaManager;

    public PhoneNumberExternalAuthenticationSource(CaptchaManager captchaManager)
    {
        this.captchaManager=captchaManager;
    }
    /// <inheritdoc/>
    public override string Name { get; } = "SMS验证码登录";

    /// <inheritdoc/>
    public override async Task<bool> TryAuthenticateAsync(string phoneNumber, string token, Tenant tenant)
    {
        //for test
        //return true;
        var currentItem = await captchaManager.GetToken(token);
        if (currentItem==null || currentItem.PhoneNumber!=phoneNumber || currentItem.Purpose!=CaptchaPurpose.LOGIN)
        {
            return false;
        }
        await captchaManager.RemoveToken(token);
        return true;
    }

    /// <inheritdoc/>
    public override Task<User> CreateUserAsync(string userNameOrEmailAddress, Tenant tenant)
    {
        var seed = Guid.NewGuid().ToString("N").Substring(0, 7);
        var surname = "手";
        var name = "机用户"+seed;
        var userName = PinyinUtil.PinYin(surname+name);

            var result = new User()
            {
                Surname = surname,
                Name = name,
                UserName =  userName,
                IsPhoneNumberConfirmed = true,
                IsActive=true,
                TenantId = tenant?.Id,
                PhoneNumber = userNameOrEmailAddress,
                Settings = null,
                IsEmailConfirmed = true,
                EmailAddress=$"{userName}@abc.com"
            };
        return Task.FromResult(result);

    }

    /// <inheritdoc/>
    public override Task UpdateUserAsync(User user, Tenant tenant)
    {
        return Task.FromResult(0);
    }

}

配置

在Web.Core项目中的WebCoreModule文件中,将PhoneNumberExternalAuthenticationSource添加至扩展身份验证源配置中

private void ConfigureExternalAuth()
{
    var userManagementConfig = IocManager.Resolve<IUserManagementConfig>();
    userManagementConfig.ExternalAuthenticationSources.Add(typeof(PhoneNumberExternalAuthenticationSource));
}

在Web.Host项目中的 appsettings.json 文件中,添加AliyunSms库的相关配置,详细说明请参考AbpBoilerplate.Sms

  "AliyunSms": {
    "RegionId": "cn-hangzhou",
    "AccessKey": "{Your AccessKey}",  //阿里云后台管理页面中获取AccessKey
    "AccessKeySecret": "{Your AccessKeySecret}"  //阿里云后台管理页面中获取AccessKeySecret
  },

至此,后端的所有任务结束,下一章将介绍前端项目的搭建

项目地址

Github:matoapp-samples

标签:免密,return,string,await,Abp,Zero,Task,user,public
From: https://www.cnblogs.com/jevonsflash/p/16848702.html

相关文章

  • Abp.Zero 手机号免密登录验证与号码绑定功能的实现(三):网页端开发
    前端代码的框架采用vue.js+elementUI这套较为简单的方式实现,以及typescript语法更方便阅读。首先来编写发送验证码函数,登录,绑定,解绑的业务都需要发送验证码功能,通过cu......
  • ABP 集成ActiveMQ客户端
    客户端代码1publicclassActiveMQConnectionService2{3publicActiveProducerOptionactiveProducerOptions;4privatereadonlyI......
  • ABP Value cannot be null. (Parameter 'unitOfWork')
    ABPValuecannotbenull.(Parameter'unitOfWork') 解决方式将需要处理的代码放置到如下位置privatereadonlyIUnitOfWorkManager_unitOfWorkManager;using(v......
  • OpenMediaVault 6 安装 Zerotier
    1.首先安装Curlsudoaptinstallcurl2.安装Zerotiersudowgethttps://download.zerotier.com/RELEASES/1.10.1/dist/debian/buster/zerotier-one_1.10.1_amd64.de......
  • linux 如何ssh免密登录
    需求:因为有多台服务器,需要互相拷贝数据,每次都要输入密码有些麻烦。所以,想免密登录。背景:有两台服务器:服务器A:192.168.49.171 服务器B:192.168.49.160 需......
  • SET DECIMAL_V2=FALSE及UDF ERROR: Cannot divide decimal by zero及Incompatible ret
    概述最近在全职负责一款数据产品的升级改造。因旧版平台的代码写得太乱,简直惨不忍睹;别说增加功能,已有问题的定位与修复都无从下手。用户提交的,在旧版平台能执行的SQL语句,在......
  • LeetCode_Array_73. Set Matrix Zeroes (C++)
    目录​​1,题目描述​​​​2,思路​​​​3,代码【C++】​​​​4,测试效果​​1,题目描述Givenamxnmatrix,ifanelementis0,setitsentirerowandcolumnto0.Do......
  • linux配置免密钥登录
    1.ssh命令在linux中,可以通过ssh命令来登录另一台服务器。打开两台linux虚拟机,一台Linux01的ip为192.168.226.128,另一台linux02为192.168.226.129,开机后在linux01终端输入......
  • C2. Make Nonzero Sum (hard version)
    C2.MakeNonzeroSum(hardversion)timelimitpertest2secondsmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputThisi......
  • 【linux】两台服务器免密传输
    两台服务器免密传输参考:两台服务器免密传输A,B两台机子想免密传输如果没有做免密传输,每次都需要输入密码,就非常麻烦个人只做了A向B传输文件的操作,操作步骤如下:1、在A......