8、ABPZero系列教程之拼多多卖家工具 添加手机注册登录功能

  现在网站基本都用手机注册,很少用邮箱注册,本篇内容比较多,代码我会尽量加备注,有些操作需要连续添加几个文件才不报错,如果VS显示错误,请继续后续步骤。

前面已经有一篇文章讲到集成短信发送模块:http://www.cnblogs.com/shensigzs/category/1147235.html

在此基础上才能做手机注册功能,没有完成的同学请先去整合后再回来。

语言文件

AbpZeroTemplate-zh-CN.xml文件末尾添加如下键值对:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Localization\AbpZeroTemplate\AbpZeroTemplate-zh-CN.xml

<text name="MobileRegister" value="手机注册" />
<text name="OccupiedMobilePhone" value="手机号码已注册或被占用" />
<text name="MobilePhone" value="手机号码" />

 

 

添加模型文件

在Web项目下Models\Account目录下添加MobileRegisterViewModel.cs,代码如下:

文件路径:D:\abpweb\PddSellerAssistant\PddSellerAssistant.Web\Models\Account\MobileRegisterViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using Abp.Auditing;
using MyCompanyName.AbpZeroTemplate.Authorization.Users;
using MyCompanyName.AbpZeroTemplate.Security;
using MyCompanyName.AbpZeroTemplate.Validation;
using MyCompanyName.AbpZeroTemplate.MultiTenancy;

namespace MyCompanyName.AbpZeroTemplate.Web.Models.Account
{
    public class MobileRegisterViewModel : IValidatableObject
    {
        [StringLength(Tenant.MaxTenancyNameLength)]
        public string TenancyName { get; set; }
        /// <summary>
        /// 手机号码
        /// </summary>
        [Required]
        [StringLength(User.MaxMobilePhoneLength)]
        public string MobilePhone { get; set; }

        /// <summary>
        /// 手机验证码
        /// </summary>
        [Required]
        [StringLength(User.MobileCodeLength)]
        public string MobilePhoneCode { get; set; }

        [StringLength(User.MaxPlainPasswordLength)]
        [DisableAuditing]
        public string Password { get; set; }
        public PasswordComplexitySetting PasswordComplexitySetting { get; set; }
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (!string.IsNullOrWhiteSpace(MobilePhone))
            {
                if (new ValidationHelper().IsPhoneNumber(MobilePhone) == false)
                {
                    yield return new ValidationResult("您输入的手机号码无效 !");
                }
            }
            else
            {
                yield return new ValidationResult("手机号码不能为空 !");
            }
        }
    }
}

 

Core项目

User.cs类添加如下代码:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Authorization\Users\User.cs

public const int MaxMobilePhoneLength = 11;
public const int MobileCodeLength = 6;

 

再打开ValidationHelper.cs,添加如下代码:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Validation\ValidationHelper.cs

/// <summary>
        /// 验证手机号是否有效
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public bool IsPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrWhiteSpace(phoneNumber))
            {
                return false;
            }
            string pattern = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$";
            return Regex.IsMatch(phoneNumber, pattern);

        }

 

 UserStore.cs类添加如下代码:

文件路径:D:\abpweb\PddSellerAssistant\PddSellerAssistant.Core\Authorization\Users\UserStore.cs

private readonly IRepository<User, long> _userRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;

 

 _userRepository = userRepository;
_unitOfWorkManager = unitOfWorkManager;
#region 扩展方法
        /// <summary>
        /// 按手机号码查询用户
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public virtual async Task<User> FindByPhoneNumberAsync(string phoneNumber)
        {

            return await _userRepository.FirstOrDefaultAsync(
                user => user.PhoneNumber == phoneNumber
                );
        }

        [UnitOfWork]
        public virtual async Task<User> FindByPhoneNumberAsync(int? tenantId, string phoneNumber)
        {
            using (_unitOfWorkManager.Current.SetTenantId(tenantId))
            {
                return await FindByPhoneNumberAsync(phoneNumber);
            }
        }
        #endregion

 

AbpZeroTemplateConsts.cs添加如下代码:

文件路径:D:\abpweb\PddSellerAssistant\PddSellerAssistant.Core\AbpZeroTemplateConsts.cs

#region 手机短信模板
        /// <summary>
        /// 手机短信验证码通用模板
        /// </summary>
        public const string SmsTemplateCommonCode = "SMS_119088461";
        #endregion

 

UserManager.cs 重写CreateAsync、CheckDuplicateUsernameOrEmailAddressAsync方法,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Authorization\Users\UserManager.cs

public override async Task<IdentityResult> CreateAsync(User user)
        {
            var result = await CheckDuplicateUsernameOrEmailAddressAsync(user.Id, user.UserName, user.EmailAddress);
            if (!result.Succeeded)
            {
                return result;
            }
            if (string.IsNullOrWhiteSpace(user.EmailAddress))
            {
                user.EmailAddress = string.Empty;
            }


            var tenantId = GetCurrentTenantId();
            if (tenantId.HasValue && !user.TenantId.HasValue)
            {
                user.TenantId = tenantId.Value;
            }

            try
            {
                return await base.CreateAsync(user);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

        }

        public override async Task<IdentityResult> CheckDuplicateUsernameOrEmailAddressAsync(long? expectedUserId, string userName, string emailAddress)
        {
            var user = (await FindByNameAsync(userName));
            if (user != null && user.Id != expectedUserId)
            {
                return AbpIdentityResult.Failed(string.Format(L("Identity.DuplicateName"), userName));
            }


            return IdentityResult.Success;
        }

        private int? GetCurrentTenantId()
        {
            if (_unitOfWorkManager.Current != null)
            {
                return _unitOfWorkManager.Current.GetTenantId();
            }

            return AbpSession.TenantId;
        }

        private string L(string name)
        {
            return LocalizationManager.GetString(AbpZeroConsts.LocalizationSourceName, name);
        }

 

Application项目 

MyAbpLoginResultType.cs添加这个类,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Application\Authorization\MyAbpLoginResultType.cs

namespace MyCompanyName.AbpZeroTemplate.Authorization
{
    public enum MyAbpLoginResultType : byte
    {
        /// <summary>
        /// 手机号码未验证
        /// </summary>
        UserMobilePhoneNotConfirmed = 10
    }
}

 

 

LogInManager.cs扩展这个类,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Application\Authorization\LogInManager.cs

private readonly IMultiTenancyConfig _multiTenancyConfig;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IRepository<Tenant> _tenantRepository;
private readonly AbpUserManager<Role, User> _userManager;
private readonly UserStore _userStore;

 

public LogInManager(
            UserManager userManager, 
            IMultiTenancyConfig multiTenancyConfig, 
            IRepository<Tenant> tenantRepository, 
            IUnitOfWorkManager unitOfWorkManager, 
            ISettingManager settingManager, 
            IRepository<UserLoginAttempt, long> userLoginAttemptRepository, 
            IUserManagementConfig userManagementConfig, 
            IIocResolver iocResolver, 
            RoleManager roleManager,
            UserStore userStore)
            : base(
                  userManager, 
                  multiTenancyConfig, 
                  tenantRepository, 
                  unitOfWorkManager, 
                  settingManager, 
                  userLoginAttemptRepository, 
                  userManagementConfig, 
                  iocResolver, 
                  roleManager)
        {
            _multiTenancyConfig = multiTenancyConfig;
            _unitOfWorkManager = unitOfWorkManager;
            _tenantRepository = tenantRepository;
            _userManager = userManager;
            _userStore = userStore;
        }

 

public virtual async Task<AbpLoginResult<Tenant, User>> LoginByMobileAsync(string mobilePhone, string plainPassword, string tenancyName = null,
            bool shouldLockout = true)
        {
            var result = await LoginByMobileAsyncInternal(mobilePhone, plainPassword, tenancyName, shouldLockout);
            await SaveLoginAttempt(result, tenancyName, mobilePhone);
            return result;
        }

        protected async Task<AbpLoginResult<Tenant, User>> LoginByMobileAsyncInternal(string mobilePhone, string plainPassword, string tenancyName, bool shouldLockout)
        {
            if (mobilePhone.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(mobilePhone));
            }

            if (plainPassword.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(plainPassword));
            }

            //Get and check tenant
            Tenant tenant = null;
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                if (!_multiTenancyConfig.IsEnabled)
                {
                    tenant = await GetDefaultTenantAsync();
                }
                else if (!string.IsNullOrWhiteSpace(tenancyName))
                {
                    tenant = await _tenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
                    if (tenant == null)
                    {
                        return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidTenancyName);
                    }

                    if (!tenant.IsActive)
                    {
                        return new AbpLoginResult<Tenant, User>(AbpLoginResultType.TenantIsNotActive, tenant);
                    }
                }
            }

            var tenantId = tenant == null ? (int?)null : tenant.Id;
            using (_unitOfWorkManager.Current.SetTenantId(tenantId))
            {
                var user = await _userStore.FindByPhoneNumberAsync(tenantId, mobilePhone);
                if (user == null)
                {
                    return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidUserNameOrEmailAddress, tenant);
                }

                _userManager.InitializeLockoutSettings(tenantId);

                if (await _userManager.IsLockedOutAsync(user.Id))
                {
                    return new AbpLoginResult<Tenant, User>(AbpLoginResultType.LockedOut, tenant, user);
                }

                var verificationResult = _userManager.PasswordHasher.VerifyHashedPassword(user.Password, plainPassword);
                if (verificationResult != PasswordVerificationResult.Success)
                {
                    if (shouldLockout)
                    {
                        if (await TryLockOutAsync(tenantId, user.Id))
                        {
                            return new AbpLoginResult<Tenant, User>(AbpLoginResultType.LockedOut, tenant, user);
                        }
                    }

                    return new AbpLoginResult<Tenant, User>(AbpLoginResultType.InvalidPassword, tenant, user);
                }

                await _userManager.ResetAccessFailedCountAsync(user.Id);

                return await CreateLoginByMobileResultAsync(user, tenant);
            }
        }

        protected async Task<AbpLoginResult<Tenant, User>> CreateLoginByMobileResultAsync(User user, Tenant tenant = null)
        {
            if (!user.IsActive)
            {
                return new AbpLoginResult<Tenant, User>(AbpLoginResultType.UserIsNotActive);
            }

            if (!user.IsPhoneNumberConfirmed)
            {
                return new AbpLoginResult<Tenant, User>((AbpLoginResultType)MyAbpLoginResultType.UserMobilePhoneNotConfirmed);
            }

            user.LastLoginTime = Clock.Now;

            await _userManager.AbpStore.UpdateAsync(user);

            await _unitOfWorkManager.Current.SaveChangesAsync();

            return new AbpLoginResult<Tenant, User>(
                tenant,
                user,
                await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
            );
        }

 

 

Web项目

CodeHelper.cs添加此类,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Helpers\CodeHelper.cs

/// <summary>
        /// 生成6位手机验证码
        /// </summary>
        /// <returns></returns>
        public static string SetNewPhoneCode()
        {
            var c = RandomHelper.GetRandom(100000, 999999);
            return c + "";
        }

 

AccountController.cs添加如下代码,大概351行位置:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Controllers\AccountController.cs

/// <summary>
        /// 手机注册
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ActionResult RegisterByMobile()
        {
            return MobileRegisterView(new MobileRegisterViewModel
            {
                TenancyName = _tenancyNameFinder.GetCurrentTenancyNameOrNull(),
                PasswordComplexitySetting = JsonConvert.DeserializeObject<PasswordComplexitySetting>(SettingManager.GetSettingValue(AppSettings.Security.PasswordComplexity))
            });

        }

        public ActionResult MobileRegisterView(MobileRegisterViewModel model)
        {
            CheckSelfRegistrationIsEnabled();

            ViewBag.IsMultiTenancyEnabled = _multiTenancyConfig.IsEnabled;

            return View("RegisterByMobile", model);
        }

 

 [HttpPost]
        [UnitOfWork]
        public virtual async Task<ActionResult> RegisterByMobile(MobileRegisterViewModel model)
        {
            try
            {

                CheckSelfRegistrationIsEnabled();
                VaildateMobile(model.MobilePhoneCode);
                //判断手机号是否被占用
                var ur = await _userManager.Users.Where(
                u => u.PhoneNumber == model.MobilePhone
                ).FirstOrDefaultAsync();
                if (ur != null)
                {
                    throw new UserFriendlyException(L("OccupiedMobilePhone"));
                }

                if (!_multiTenancyConfig.IsEnabled)
                {
                    model.TenancyName = Tenant.DefaultTenantName;
                }
                else if (model.TenancyName.IsNullOrEmpty())
                {
                    throw new UserFriendlyException(L("TenantNameCanNotBeEmpty"));
                }

                CurrentUnitOfWork.SetTenantId(null);

                var tenant = await GetActiveTenantAsync(model.TenancyName);

                CurrentUnitOfWork.SetTenantId(tenant.Id);

                if (!await SettingManager.GetSettingValueForTenantAsync<bool>(AppSettings.UserManagement.AllowSelfRegistration, tenant.Id))
                {
                    throw new UserFriendlyException(L("SelfUserRegistrationIsDisabledMessage_Detail"));
                }

                await _userPolicy.CheckMaxUserCountAsync(tenant.Id);

                //Getting tenant-specific settings
                var isNewRegisteredUserActiveByDefault = await SettingManager.GetSettingValueForTenantAsync<bool>(AppSettings.UserManagement.IsNewRegisteredUserActiveByDefault, tenant.Id);
                var isEmailConfirmationRequiredForLogin = await SettingManager.GetSettingValueForTenantAsync<bool>(AbpZeroSettingNames.UserManagement.IsEmailConfirmationRequiredForLogin, tenant.Id);

                var user = new User
                {
                    TenantId = tenant.Id,
                    IsActive = isNewRegisteredUserActiveByDefault,
                    PhoneNumber = model.MobilePhone,
                    IsPhoneNumberConfirmed = true
                };

                ExternalLoginInfo externalLoginInfo = null;
                //用户名或密码为空,抛出异常
                if (model.MobilePhone.IsNullOrEmpty() || model.Password.IsNullOrEmpty())
                {
                    throw new UserFriendlyException(L("FormIsNotValidMessage"));
                }

                user.UserName = model.MobilePhone;
                user.Password = new PasswordHasher().HashPassword(model.Password);

                user.Roles = new List<UserRole>();
                foreach (var defaultRole in await _roleManager.Roles.Where(r => r.IsDefault).ToListAsync())
                {
                    user.Roles.Add(new UserRole(tenant.Id, user.Id, defaultRole.Id));
                }
                
                CheckErrors(await _userManager.CreateAsync(user));
                await _unitOfWorkManager.Current.SaveChangesAsync();


                //通知
                await _notificationSubscriptionManager.SubscribeToAllAvailableNotificationsAsync(user.ToUserIdentifier());
                await _appNotifier.WelcomeToTheApplicationAsync(user);
                await _appNotifier.NewUserRegisteredAsync(user);

                //如果可能,直接登录
                if (user.IsActive && user.IsPhoneNumberConfirmed)
                {
                    AbpLoginResult<Tenant, User> loginResult;
                    loginResult = await GetLoginByMobileResultAsync(user.UserName, model.Password, tenant.TenancyName);

                    if (loginResult.Result == AbpLoginResultType.Success)
                    {
                        await SignInAsync(loginResult.User, loginResult.Identity);
                        
                        return Redirect(Url.Action("Index", "Application"));
                    }

                    Logger.Warn("新注册的用户无法登录。 这不应该是正常。 登录结果: " + loginResult.Result);
                }

                return View("RegisterResult", new RegisterResultViewModel
                {
                    TenancyName = tenant.TenancyName,
                    NameAndSurname = user.Name + " " + user.Surname,
                    UserName = user.UserName,
                    EmailAddress = user.EmailAddress,
                    IsActive = user.IsActive,
                    IsEmailConfirmationRequired = isEmailConfirmationRequiredForLogin
                });
            }
            catch (UserFriendlyException ex)
            {
                ViewBag.IsMultiTenancyEnabled = _multiTenancyConfig.IsEnabled;
                ViewBag.UseCaptcha = UseCaptchaOnRegistration();
                ViewBag.ErrorMessage = ex.Message;
                ViewBag.ErrorDetails = ex.Details;

                return View("RegisterByMobile", model);
            }
        }

 

 

/// <summary>
        /// 手机验证码验证
        /// </summary>
        /// <param name="mobilePhoneCode"></param>
        private void VaildateMobile(string mobilePhoneCode)
        {
            if (mobilePhoneCode.Length != Authorization.Users.User.MobileCodeLength)
            {
                throw new UserFriendlyException(string.Format("验证码必须为 {0} 位!", Authorization.Users.User.MobileCodeLength));
            }
            //手机验证码效验
            var phoneCode = Session["PhoneCode"];
            var now = Session["PhoneCodeDateTime"];
            if (phoneCode == null || string.IsNullOrWhiteSpace(phoneCode.ToString()))
            {
                throw new UserFriendlyException("您输入的验证码无效!");
            }
            var nowTime = Convert.ToDateTime(now);
            var t = DateTime.Now - nowTime;
            if (t.TotalSeconds >= 180)
            {
                throw new UserFriendlyException("您输入的验证码无效!");
            }
            if (!mobilePhoneCode.Equals(phoneCode.ToString()))
            {
                throw new UserFriendlyException("您输入的验证码不正确!");
            }
        }

        private async Task<AbpLoginResult<Tenant, User>> GetLoginByMobileResultAsync(string mobilePhone, string password, string tenancyName)
        {
            var loginResult = await _logInManager.LoginByMobileAsync(mobilePhone, password, tenancyName);

            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    return loginResult;
                default:
                    throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, mobilePhone, tenancyName);
            }
        }

 

VerificationCodeController.cs添加此控制器,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Controllers\VerificationCodeController.cs

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Abp.Net.Sms;
using Abp.UI;
using MyCompanyName.AbpZeroTemplate.Authorization.Users;
using MyCompanyName.AbpZeroTemplate.MultiTenancy;
using MyCompanyName.AbpZeroTemplate.Validation;
using MyCompanyName.AbpZeroTemplate.Web.Helpers;

namespace MyCompanyName.AbpZeroTemplate.Web.Controllers
{
    public class VerificationCodeController : AbpZeroTemplateControllerBase
    {
        private readonly UserManager _userManager;
        private readonly ISmsSender _smsSender;
        private readonly TenantManager _tenantManager;
        private readonly IUserEmailer _userEmailer;

        public VerificationCodeController(UserManager userManager,
            ISmsSender smsSender,
            TenantManager tenantManager,
            IUserEmailer userEmailer)
        {
            _userManager = userManager;
            _smsSender = smsSender;
            _tenantManager = tenantManager;
            _userEmailer = userEmailer;
        }
        #region 手机

        /// <summary>
        /// 注册时使用,发送手机验证码
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<JsonResult> SendMobileCode(string phoneNumber)
        {
            try
            {
                if (!new ValidationHelper().IsPhoneNumber(phoneNumber))
                {
                    throw new UserFriendlyException("您输入了无效的手机号码!");
                }
                //检查手机是否已被注册
                var user = await _userManager.Users.Where(
                u => u.PhoneNumber == phoneNumber
                ).FirstOrDefaultAsync();

                if (user != null)
                {
                    throw new UserFriendlyException(L("OccupiedMobilePhone"));
                }
                //生成6位数字验证码
                var code = CodeHelper.SetNewPhoneCode();
                //发送验证码
                await _smsSender.SendAsync(phoneNumber, AbpZeroTemplateConsts.SmsTemplateCommonCode, "{\"code\":\"" + code + "\"}");
                //存储验证码、手机号、时间,以备验证使用
                Session["PhoneCode"] = code;
                Session["PhoneNumber"] = phoneNumber;
                Session["PhoneCodeDateTime"] = DateTime.Now;
                return Json("OK", JsonRequestBehavior.DenyGet);
            }
            catch (Exception ex)
            {
                throw new UserFriendlyException(ex.Message);
            }
        }


        
        /// <summary>
        ///验证手机时使用,发送手机验证码
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<JsonResult> SendMobileCodeByVerificationMobile(string phoneNumber)
        {
            try
            {
                if (!new ValidationHelper().IsPhoneNumber(phoneNumber))
                {
                    throw new UserFriendlyException("您输入了无效的手机号码!");
                }
                //检查手机是否已被注册
                var user = await _userManager.Users.Where(
                u => u.PhoneNumber == phoneNumber && u.Id != AbpSession.UserId
                ).FirstOrDefaultAsync();

                if (user != null)
                {
                    throw new UserFriendlyException(L("OccupiedMobilePhone"));
                }
                //生成6位数字验证码
                var code = CodeHelper.SetNewPhoneCode();
                //发送验证码
                await _smsSender.SendAsync(phoneNumber, AbpZeroTemplateConsts.SmsTemplateCommonCode, "{\"code\":\"" + code + "\"}");
                //存储验证码、手机号、时间,以备验证使用
                Session["PhoneCode"] = code;
                Session["PhoneNumber"] = phoneNumber;
                Session["PhoneCodeDateTime"] = DateTime.Now;
                return Json("OK", JsonRequestBehavior.DenyGet);
            }
            catch (Exception ex)
            {
                throw new UserFriendlyException(ex.Message);
            }
        }

        #endregion

        #region private
        /// <summary>
        /// 检查手机号码是否已被注册,未注册抛出异常
        /// </summary>
        /// <param name="mobilePhone"></param>
        /// <returns></returns>
        private async Task<User> GetUserByCheckingMobile(string mobilePhone)
        {
            var user = await _userManager.Users.Where(
                u => u.PhoneNumber == mobilePhone
                ).FirstOrDefaultAsync();

            if (user == null)
            {
                throw new UserFriendlyException(L("InvalidMobilePhone"));
            }

            return user;
        }
        
        #endregion
    }
}

 

添加视图

添加RegisterByMobile.cshtml视图文件,代码如下:

文件路径:D:\abpweb\PddSellerAssistant\PddSellerAssistant.Web\Views\Account\RegisterByMobile.cshtml

@model MyCompanyName.AbpZeroTemplate.Web.Models.Account.MobileRegisterViewModel
@using System.Web.Script.Serialization
@using Abp.Extensions
@using Abp.Web.Mvc.Extensions
@using MyCompanyName.AbpZeroTemplate.MultiTenancy
@using Recaptcha.Web
@using Recaptcha.Web.Mvc
@section Scripts
{
    <script>
        window.passwordComplexitySetting = @(new JavaScriptSerializer().Serialize(Model.PasswordComplexitySetting).Replace("\"", ""));
    </script>
    @Html.IncludeScript("~/Views/Account/RegisterByMobile.js")
}
<form class="register-form" action="@Url.Action("RegisterByMobile")" method="post">

    <h3>@L("MobileRegister")</h3>

    @if (@ViewBag.ErrorMessage != null)
    {
        <div class="alert alert-danger">
            <i class="fa fa-warning"></i> @ViewBag.ErrorMessage
            @if (@ViewBag.ErrorDetails != null)
            {
                <br />@ViewBag.ErrorDetails
            }
        </div>
    }

    @Html.AntiForgeryToken()

    @if (ViewBag.IsMultiTenancyEnabled)
    {
        if (Model.TenancyName.IsNullOrEmpty())
        {
            <p class="hint">
                @L("TenantInformations")
            </p>
            <div class="form-group">
                <label class="control-label visible-ie8 visible-ie9">@L("TenancyName")</label>
                <input class="form-control placeholder-no-fix input-ltr" type="text" placeholder="@L("TenancyName")" name="TenancyName" value="@(Model.TenancyName ?? "")" required maxlength="@Tenant.MaxTenancyNameLength" />
            </div>
        }
        else
        {
            <input type="hidden" name="TenancyName" value="@Model.TenancyName" />
        }
    }

    <p class="hint">
        @L("AccountSettings")
    </p>
    <div class="form-group">
        <label class="control-label visible-ie8 visible-ie9">@L("MobilePhone")</label>
        <input class="form-control placeholder-no-fix" type="text" placeholder="@L("MobilePhone")" id="MobilePhone" name="MobilePhone" required value="@Model.MobilePhone" maxlength="@MyCompanyName.AbpZeroTemplate.Authorization.Users.User.MaxMobilePhoneLength" />
    </div>
    <div class="form-group">
        <div class="input-group input-group-lg">

            <div class="input-group-control">
                <input type="text" class="form-control input-sm" autocomplete="off" id="MobileCode" name="MobilePhoneCode" value="" required placeholder="验证码">
            </div>
            <span class="input-group-btn btn-right">
                <button id="SendMobileCode" class="btn green-haze" type="button">发送验证码</button>
            </span>
        </div>
    </div>
    <div class="form-group">
        <label class="control-label visible-ie8 visible-ie9">@L("Password")</label>
        <input class="form-control placeholder-no-fix" type="password" autocomplete="off" id="RegisterPassword" placeholder="@L("Password")" name="Password" required />
    </div>
    <div class="form-group">
        <label class="control-label visible-ie8 visible-ie9">@L("PasswordRepeat")</label>
        <input class="form-control placeholder-no-fix" type="password" autocomplete="off" placeholder="@L("PasswordRepeat")" name="PasswordRepeat" required />
    </div>


    <div class="form-actions">
        <a href="@Url.Action("Login", "Account")"><button type="button" id="register-back-btn" class="btn btn-default">@L("Back")</button></a>
        <a href="@Url.Action("Register","Account")">邮箱注册</a>
        <button type="submit" id="register-submit-btn" class="btn btn-success uppercase pull-right">@L("Submit")</button>
    </div>
</form>

 

 

JS文件

添加一个跟视图名称一样的JS文件 RegisterByMobile.js,代码如下:

 文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Views\Account\RegisterByMobile.js

var CurrentPage = function () {

    jQuery.validator.addMethod("customUsername", function (value, element) {
        if (value === $('input[name="MobilePhoneCode"]').val()) {
            return true;
        }

        return !$.validator.methods.email.apply(this, arguments);
    }, abp.localization.localize("RegisterFormUserNameInvalidMessage"));

    var _passwordComplexityHelper = new app.PasswordComplexityHelper();

    var handleRegister = function () {

        $('.register-form').validate({
            rules: {
                PasswordRepeat: {
                    equalTo: "#RegisterPassword"
                },
                MobilePhone: {
                    required: true,
                },
                MobileCode: {
                    required: true,
                }
            },

            submitHandler: function (form) {
                form.submit();
            }
        });

        var $element = $('#RegisterPassword');
        _passwordComplexityHelper.setPasswordComplexityRules($element, window.passwordComplexitySetting);
        /**
         发送验证码
         */
        $(sendMobileCodeBtn).click(function () {
            var phoneNumber = $("#MobilePhone").val();
            if (checkMobile(phoneNumber) == false) {
                return false;
            }

            curCount = count;
            abp.ajax({
                contentType: app.consts.contentTypes.formUrlencoded,
                url: '/VerificationCode/SendMobileCode',
                data: { phoneNumber: phoneNumber }
            }).done(function (result) {
                if (result.result == "OK") {
                    // 设置按钮显示效果,倒计时
                    $(sendMobileCodeBtn).attr("disabled", "true");
                    $(sendMobileCodeBtn).text("请在" + curCount + "秒内输入验证码");
                    InterValObj = window.setInterval(SetRemainTime, 1000); // 启动计时器,1秒执行一次
                } else {
                    $(sendMobileCodeBtn).val("重新发送验证码");
                }
            });
        });


    }

    return {
        init: function () {
            handleRegister();
        }
    };

}();
var InterValObj; //timer变量,控制时间
var count = 60 * 3; //间隔函数,1秒执行
var curCount;//当前剩余秒数
var codeLength = 6;//验证码长度
var sendMobileCodeBtn = $("#SendMobileCode");
//timer处理函数
function SetRemainTime() {
    if (curCount == 0) {
        window.clearInterval(InterValObj);// 停止计时器
        $(sendMobileCodeBtn).removeAttr("disabled");// 启用按钮
        $(sendMobileCodeBtn).text("重新发送验证码");
        code = ""; // 清除验证码。如果不清除,过时间后,输入收到的验证码依然有效
    } else {
        curCount--;
        $(sendMobileCodeBtn).text("请在" + curCount + "秒内输入验证码");
    }
}

function checkMobile(phone) {
    if (!(/^1[3|4|5|8][0-9]\d{4,8}$/.test(phone))) {
        abp.message.error('您输入了无效的手机号', '错误');
        return false;
    }
}

 

 手机注册入口

 Register.cshtml添加手机号注册连接,代码如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Views\Account\Register.cshtml

<div class="form-actions">
        <a href="@Url.Action("Login", "Account")"><button type="button" id="register-back-btn" class="btn btn-default">@L("Back")</button></a>
        <a href="@Url.Action("RegisterByMobile","Account")">手机号注册</a>
        <button type="submit" id="register-submit-btn" class="btn btn-success uppercase pull-right">@L("Submit")</button>
    </div>

 

 保存生成项目,浏览器打开注册页面,如下图所示:

 

 

 

 

注册成功会自动登录系统,此时注销用户,再次登录会提示“登录失败”,接下来修改登录功能,使之同时支持手机、邮箱、用户名登录。

 

登录功能修改

AccountController.cs修改Login Post方法,143行位置代码修改如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Web\Controllers\AccountController.cs

 

AbpLoginResult<Tenant,
            Authorization.Users.User > loginResult = null;
            if (new ValidationHelper().IsPhoneNumber(loginModel.UsernameOrEmailAddress))
            {
                loginResult =
                    await
                        GetLoginByMobileResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password,
                            loginModel.TenancyName);
            }
            else
            {
                loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);
            }

 

 

AbpZeroTemplate-zh-CN.xml ,代码修改如下:

文件路径:D:\abp version\aspnet-zero-3.4.0\aspnet-zero-3.4.0\src\MyCompanyName.AbpZeroTemplate.Core\Localization\AbpZeroTemplate\AbpZeroTemplate-zh-CN.xml  

<text name="UserNameOrEmail" value="手机或用户名或邮箱地址" />

 

 

 生成项目,再次以手机、邮箱、用户名登录,已经都可以正常登录。

手机注册登录功能到这里修改完成,篇幅很多,基本把整个解决方案翻了一篇。

 

 返回总目录

 

posted @ 2018-01-15 20:11 李子深 阅读(...) 评论(...) 编辑 收藏
李子深的博客

真诚赞赏,手留余香

使用微信扫描二维码完成支付