接下来我们重写原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

原文地址:http://www.cnblogs.com/jevonsflash/p/16848702.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性