From 6ebbdd42a4f83a14ef22eba3539ceaa8256951a7 Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Thu, 19 Nov 2020 13:39:54 +0800
Subject: [PATCH] The SMS verification code should be generated through the
user security token
---
.../LINGYUN.MicroService.IdentityServer.sln | 45 +-
...NGYUN.MicroService.IdentityServerAdmin.sln | 30 +-
...N.Abp.Account.Application.Contracts.csproj | 10 +-
.../AbpAccountApplicationContractsModule.cs | 22 +-
...mberRegisterDto.cs => PhoneRegisterDto.cs} | 16 +-
...rdResetDto.cs => PhoneResetPasswordDto.cs} | 12 +-
...rifyDto.cs => SendPhoneRegisterCodeDto.cs} | 6 +-
.../Dto/SendPhoneResetPasswordCodeDto.cs | 15 +
...gisterDto.cs => SendPhoneSigninCodeDto.cs} | 3 +-
.../Abp/Account/Dto/WeChatRegisterDto.cs | 11 +-
.../LINGYUN/Abp/Account/IAccountAppService.cs | 44 +-
.../Account/Localization/Resources/en.json | 15 +
.../Localization/Resources/zh-Hans.json | 15 +
.../LINGYUN.Abp.Account.Application.csproj | 2 +-
.../Account/AbpAccountApplicationModule.cs | 5 +-
.../LINGYUN/Abp/Account/AccountAppService.cs | 402 ++++++-------
.../LINGYUN.Abp.Account.Domain.Shared.csproj | 12 +-
.../AccountSettingDefinitionProvider.cs | 63 --
.../Abp/Account/AccountSettingNames.cs | 23 -
.../Account/Localization/AccountResource.cs | 9 -
.../Account/Localization/Resources/en.json | 20 -
.../Localization/Resources/zh-Hans.json | 20 -
.../LINGYUN.Abp.Account.Domain.csproj | 2 +-
.../Identity/PhoneNumberUserValidator.cs | 50 --
.../LINGYUN.Abp.Account.HttpApi.csproj | 2 +-
.../Abp/Account/AbpAccountHttpApiModule.cs | 20 +-
.../LINGYUN/Abp/Account/AccountController.cs | 37 +-
...NGYUN.Abp.AspNetCore.Mvc.Validation.csproj | 24 +
.../AbpAspNetCoreMvcValidationModule.cs | 31 +
.../AbpDataAnnotationsMetadataProvider.cs | 563 ++++++++++++++++++
.../AbpLocalizerModelMetadataProvider.cs | 69 +++
...AutoLocalizationMetadataDetailsProvider.cs | 69 +++
.../Localization/MissingFields/en.json | 7 +
.../Localization/MissingFields/zh-Hans.json | 7 +
...dressInput.cs => ChangeEmailAddressDto.cs} | 7 +-
...NumberInput.cs => ChangePhoneNumberDto.cs} | 7 +-
...ledDto.cs => ChangeTwoFactorEnabledDto.cs} | 2 +-
.../Dto/SendChangeEmailAddressCodeDto.cs | 18 +
.../Dto/SendChangePhoneNumberCodeDto.cs | 18 +
.../Abp/Identity/IIdentityUserAppService.cs | 2 +-
.../Abp/Identity/IMyProfileAppService.cs | 19 +-
.../Abp/Identity/IdentityUserAppService.cs | 2 +-
.../Abp/Identity/MyProfileAppService.cs | 69 ++-
.../Abp/Identity/IUserSecurityCodeSender.cs | 20 +
.../Abp/Identity/IdentityErrorCodes.cs | 8 +
.../LINGYUN/Abp/Identity/Localization/en.json | 20 +-
.../Abp/Identity/Localization/zh-Hans.json | 19 +-
.../Identity/Security/DefaultTotpService.cs | 121 ++++
.../Abp/Identity/Security/ITotpService.cs | 12 +
.../IdentitySettingDefinitionProvider.cs | 52 ++
.../Identity/Settings/IdentitySettingNames.cs | 25 +
.../Abp/Identity/IIdentityUserRepository.cs | 68 ++-
.../Abp/Identity/SmsSecurityTokenCacheItem.cs | 39 ++
.../Identity/PhoneNumberUserValidator.cs | 57 ++
.../EfCoreIdentityUserRepository.cs | 38 ++
.../Abp/Identity/AbpIdentityHttpApiModule.cs | 8 +
.../Abp/Identity/IdentityUserController.cs | 2 +-
.../Abp/Identity/MyProfileController.cs | 16 +-
.../AbpIdentityServerHttpApiModule.cs | 6 +
...YUN.Abp.IdentityServer.SmsValidator.csproj | 2 +-
.../SmsValidator/SmsTokenGrantValidator.cs | 13 +-
.../AuthIdentityServerModule.cs | 8 +-
.../AuthServer.Host/AuthServer.Host.csproj | 5 +-
.../EfCoreIdentityUserExtensionRepository.cs | 52 --
.../Pages/Account/SendCode.cshtml.cs | 5 +-
...AbpIdentityServerAdminHttpApiHostModule.cs | 12 +-
.../Emailing/Templates/EmailConfirmed.tpl | 5 +
...IdentityEmailTemplateDefinitionProvider.cs | 26 +
.../Templates/IdentityEmailTemplates.cs | 7 +
.../EfCoreIdentityUserExtensionRepository.cs | 42 --
...UN.Abp.IdentityServer4.HttpApi.Host.csproj | 11 +
.../Properties/launchSettings.json | 14 +-
.../UserSecurityCodeSender.cs | 66 ++
vueJs/src/api/users.ts | 35 +-
vueJs/src/views/login/index.vue | 7 +-
vueJs/src/views/register/index.vue | 7 +-
vueJs/src/views/reset-password/index.vue | 7 +-
77 files changed, 2005 insertions(+), 655 deletions(-)
rename aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/{PhoneNumberRegisterDto.cs => PhoneRegisterDto.cs} (69%)
rename aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/{PasswordResetDto.cs => PhoneResetPasswordDto.cs} (50%)
rename aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/{VerifyDto.cs => SendPhoneRegisterCodeDto.cs} (75%)
create mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneResetPasswordCodeDto.cs
rename aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/{RegisterDto.cs => SendPhoneSigninCodeDto.cs} (80%)
create mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json
create mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingDefinitionProvider.cs
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
delete mode 100644 aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpAspNetCoreMvcValidationModule.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpDataAnnotationsMetadataProvider.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpLocalizerModelMetadataProvider.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/DataAnnotationAutoLocalizationMetadataDetailsProvider.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/Localization/MissingFields/en.json
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/Localization/MissingFields/zh-Hans.json
rename aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/{ChangeEmailAddressInput.cs => ChangeEmailAddressDto.cs} (75%)
rename aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/{ChangePhoneNumberInput.cs => ChangePhoneNumberDto.cs} (75%)
rename aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/{IdentityUserTwoFactorEnabledDto.cs => ChangeTwoFactorEnabledDto.cs} (65%)
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/SendChangeEmailAddressCodeDto.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/SendChangePhoneNumberCodeDto.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IUserSecurityCodeSender.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Security/DefaultTotpService.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Security/ITotpService.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SmsSecurityTokenCacheItem.cs
create mode 100644 aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs
delete mode 100644 aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
create mode 100644 aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl
create mode 100644 aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs
create mode 100644 aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs
delete mode 100644 aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
create mode 100644 aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/UserSecurityCodeSender.cs
diff --git a/aspnet-core/LINGYUN.MicroService.IdentityServer.sln b/aspnet-core/LINGYUN.MicroService.IdentityServer.sln
index 7315746d7..12c2d55a8 100644
--- a/aspnet-core/LINGYUN.MicroService.IdentityServer.sln
+++ b/aspnet-core/LINGYUN.MicroService.IdentityServer.sln
@@ -23,12 +23,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{AF8AEC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Authorization", "modules\wechat\LINGYUN.Abp.WeChat.Authorization\LINGYUN.Abp.WeChat.Authorization.csproj", "{F656C1B2-6122-44C1-97F4-421CB4C03ED8}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{09C7BFF7-BCCB-4E02-8DAE-3B047A68011D}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Domain.Shared", "modules\account\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj", "{495A110A-8034-409B-A036-28CDF2CA9386}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Domain", "modules\account\LINGYUN.Abp.Account.Domain\LINGYUN.Abp.Account.Domain.csproj", "{650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "permission-management", "permission-management", "{2FEA83BA-2E6D-40AF-8781-12CFD042457F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Domain", "modules\permissions-management\LINGYUN.Abp.PermissionManagement.Domain\LINGYUN.Abp.PermissionManagement.Domain.csproj", "{A0A11373-635B-4343-8EE7-1DFC3611F05A}"
@@ -49,6 +43,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Authoriz
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Aliyun", "modules\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj", "{A51E2EB5-EEC0-4FB0-99B9-A0FBE0D8B0EB}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{E5E51981-864A-4B54-8E50-B5AE8B81245C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{6514E12E-D97C-4311-8301-F270D4E04A9F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{77F424CB-75F2-4D7F-8B52-BBE2E09CB423}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{644FAB8F-ED83-4539-AF43-8F8FE61EF778}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -75,14 +77,6 @@ Global
{F656C1B2-6122-44C1-97F4-421CB4C03ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F656C1B2-6122-44C1-97F4-421CB4C03ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F656C1B2-6122-44C1-97F4-421CB4C03ED8}.Release|Any CPU.Build.0 = Release|Any CPU
- {495A110A-8034-409B-A036-28CDF2CA9386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {495A110A-8034-409B-A036-28CDF2CA9386}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {495A110A-8034-409B-A036-28CDF2CA9386}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {495A110A-8034-409B-A036-28CDF2CA9386}.Release|Any CPU.Build.0 = Release|Any CPU
- {650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0}.Release|Any CPU.Build.0 = Release|Any CPU
{A0A11373-635B-4343-8EE7-1DFC3611F05A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0A11373-635B-4343-8EE7-1DFC3611F05A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0A11373-635B-4343-8EE7-1DFC3611F05A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -111,6 +105,22 @@ Global
{A51E2EB5-EEC0-4FB0-99B9-A0FBE0D8B0EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A51E2EB5-EEC0-4FB0-99B9-A0FBE0D8B0EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A51E2EB5-EEC0-4FB0-99B9-A0FBE0D8B0EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E5E51981-864A-4B54-8E50-B5AE8B81245C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E5E51981-864A-4B54-8E50-B5AE8B81245C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E5E51981-864A-4B54-8E50-B5AE8B81245C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E5E51981-864A-4B54-8E50-B5AE8B81245C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6514E12E-D97C-4311-8301-F270D4E04A9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6514E12E-D97C-4311-8301-F270D4E04A9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6514E12E-D97C-4311-8301-F270D4E04A9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6514E12E-D97C-4311-8301-F270D4E04A9F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77F424CB-75F2-4D7F-8B52-BBE2E09CB423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77F424CB-75F2-4D7F-8B52-BBE2E09CB423}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77F424CB-75F2-4D7F-8B52-BBE2E09CB423}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77F424CB-75F2-4D7F-8B52-BBE2E09CB423}.Release|Any CPU.Build.0 = Release|Any CPU
+ {644FAB8F-ED83-4539-AF43-8F8FE61EF778}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {644FAB8F-ED83-4539-AF43-8F8FE61EF778}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {644FAB8F-ED83-4539-AF43-8F8FE61EF778}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {644FAB8F-ED83-4539-AF43-8F8FE61EF778}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -124,9 +134,6 @@ Global
{F87B2BA3-40BC-4CB8-B53E-793C860F285D} = {70B8D735-1E89-4163-8EDB-56A74E374CF4}
{AF8AECC8-0F42-4FC5-B3C0-00987BA8279F} = {7C727110-59CA-495B-8143-C5DDEDE41289}
{F656C1B2-6122-44C1-97F4-421CB4C03ED8} = {AF8AECC8-0F42-4FC5-B3C0-00987BA8279F}
- {09C7BFF7-BCCB-4E02-8DAE-3B047A68011D} = {7C727110-59CA-495B-8143-C5DDEDE41289}
- {495A110A-8034-409B-A036-28CDF2CA9386} = {09C7BFF7-BCCB-4E02-8DAE-3B047A68011D}
- {650FE9CC-4A55-4F2C-A82C-EF10DEB32DF0} = {09C7BFF7-BCCB-4E02-8DAE-3B047A68011D}
{2FEA83BA-2E6D-40AF-8781-12CFD042457F} = {7C727110-59CA-495B-8143-C5DDEDE41289}
{A0A11373-635B-4343-8EE7-1DFC3611F05A} = {2FEA83BA-2E6D-40AF-8781-12CFD042457F}
{6F13C138-1D71-48F5-A404-94047242E98F} = {AF8AECC8-0F42-4FC5-B3C0-00987BA8279F}
@@ -137,6 +144,10 @@ Global
{6CB9D0F3-8D50-49B5-98E2-D777717E51E8} = {7C727110-59CA-495B-8143-C5DDEDE41289}
{C675C7DB-5825-4F64-BF76-8A4452A448D2} = {572DBB40-4637-4C01-8491-8686F7E22B45}
{A51E2EB5-EEC0-4FB0-99B9-A0FBE0D8B0EB} = {572DBB40-4637-4C01-8491-8686F7E22B45}
+ {E5E51981-864A-4B54-8E50-B5AE8B81245C} = {70B8D735-1E89-4163-8EDB-56A74E374CF4}
+ {6514E12E-D97C-4311-8301-F270D4E04A9F} = {70B8D735-1E89-4163-8EDB-56A74E374CF4}
+ {77F424CB-75F2-4D7F-8B52-BBE2E09CB423} = {70B8D735-1E89-4163-8EDB-56A74E374CF4}
+ {644FAB8F-ED83-4539-AF43-8F8FE61EF778} = {98887A8F-7040-4FA1-842F-A4C77A61ED09}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FCB77471-9ECB-4666-A316-1D6A6285A468}
diff --git a/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln b/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln
index 043bf0498..087d6dc2a 100644
--- a/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln
+++ b/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln
@@ -25,18 +25,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-server", "identity
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{BD964040-90B2-4179-A5EB-5830F5C7E073}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Domain.Shared", "modules\account\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj", "{82ACBDDA-1C77-49B6-9F33-38DFD3D4691D}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Domain", "modules\account\LINGYUN.Abp.Account.Domain\LINGYUN.Abp.Account.Domain.csproj", "{2BA25A1B-D53E-432B-BAC2-BAAC66CA390D}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application.Contracts", "modules\account\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj", "{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application", "modules\account\LINGYUN.Abp.Account.Application\LINGYUN.Abp.Account.Application.csproj", "{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.HttpApi", "modules\account\LINGYUN.Abp.Account.HttpApi\LINGYUN.Abp.Account.HttpApi.csproj", "{BB1124C0-79F4-4E72-8854-945B3F0AD76D}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Web", "modules\account\LINGYUN.Abp.Account.Web\LINGYUN.Abp.Account.Web.csproj", "{3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{E22445B9-7039-4DA1-B547-BAB437D6D2B3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}"
@@ -59,7 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{23536755-4F00-4929-9C5E-D4CABD1CC513}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{23536755-4F00-4929-9C5E-D4CABD1CC513}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}"
EndProject
@@ -79,6 +73,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.DbFinder", "modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj", "{70C4FA43-0526-48E3-B852-A21395502604}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Validation", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Validation\LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj", "{B3181D37-F379-4E16-8621-5E739C519393}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -109,14 +105,6 @@ Global
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.Build.0 = Release|Any CPU
- {82ACBDDA-1C77-49B6-9F33-38DFD3D4691D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {82ACBDDA-1C77-49B6-9F33-38DFD3D4691D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {82ACBDDA-1C77-49B6-9F33-38DFD3D4691D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {82ACBDDA-1C77-49B6-9F33-38DFD3D4691D}.Release|Any CPU.Build.0 = Release|Any CPU
- {2BA25A1B-D53E-432B-BAC2-BAAC66CA390D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2BA25A1B-D53E-432B-BAC2-BAAC66CA390D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2BA25A1B-D53E-432B-BAC2-BAAC66CA390D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2BA25A1B-D53E-432B-BAC2-BAAC66CA390D}.Release|Any CPU.Build.0 = Release|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -129,10 +117,6 @@ Global
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.Build.0 = Release|Any CPU
- {3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8}.Release|Any CPU.Build.0 = Release|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -205,6 +189,10 @@ Global
{70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -219,12 +207,9 @@ Global
{4F06C65B-22CC-466E-B3FD-3F695DD38191} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{7AB942D5-D139-4F9F-9342-71534AA3A5AC} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{BD964040-90B2-4179-A5EB-5830F5C7E073} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
- {82ACBDDA-1C77-49B6-9F33-38DFD3D4691D} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
- {2BA25A1B-D53E-432B-BAC2-BAAC66CA390D} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{BB1124C0-79F4-4E72-8854-945B3F0AD76D} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
- {3297ED1B-FB82-4EC5-ADA1-0D0390BEDBB8} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{E22445B9-7039-4DA1-B547-BAB437D6D2B3} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{B07A1763-1B37-4416-8F0C-B938C175A56D} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
@@ -246,6 +231,7 @@ Global
{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}
{70C4FA43-0526-48E3-B852-A21395502604} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}
+ {B3181D37-F379-4E16-8621-5E739C519393} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj
index 9aecfae64..e2ec82337 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj
@@ -8,11 +8,17 @@
-
+
+
-
+
+
+
+
+
+
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs
index 50ff26017..4cff95a7d 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs
@@ -1,9 +1,27 @@
-using Volo.Abp.Modularity;
+using Volo.Abp.Account.Localization;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account
{
- [DependsOn(typeof(AbpAccountDomainSharedModule))]
+ [DependsOn(
+ typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule))]
public class AbpAccountApplicationContractsModule : AbpModule
{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Get()
+ .AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources");
+ });
+ }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneNumberRegisterDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneRegisterDto.cs
similarity index 69%
rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneNumberRegisterDto.cs
rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneRegisterDto.cs
index fed5af779..3f11ff3b4 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneNumberRegisterDto.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneRegisterDto.cs
@@ -1,35 +1,43 @@
-using System.ComponentModel.DataAnnotations;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account
{
- public class PhoneNumberRegisterDto
+ public class PhoneRegisterDto
{
[Required]
[Phone]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
+ [Display(Name = "PhoneNumber")]
public string PhoneNumber { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
+ [DisplayName("Name")]
public string Name { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
+ [DisplayName("UserName")]
public string UserName { get; set; }
[EmailAddress]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
+ [DisplayName("EmailAddress")]
public string EmailAddress { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[DataType(DataType.Password)]
+ [DisplayName("Password")]
[DisableAuditing]
public string Password { get; set; }
[Required]
- [StringLength(6)]
- public string VerifyCode { get; set; }
+ [StringLength(6,MinimumLength = 6)]
+ [DisableAuditing]
+ [DisplayName("DisplayName:SmsVerifyCode")]
+ public string Code { get; set; }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PasswordResetDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneResetPasswordDto.cs
similarity index 50%
rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PasswordResetDto.cs
rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneResetPasswordDto.cs
index 899323137..b698d7492 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PasswordResetDto.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/PhoneResetPasswordDto.cs
@@ -5,11 +5,17 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account
{
- public class PasswordResetDto
+ public class PhoneResetPasswordDto
{
[Required]
[Phone]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
+
+ // 如果Dto属性和本地化内容不一致,需要指定本地化名称如下
+ // [Display(Name = "DisplayName:RequiredPhoneNumber")] //json本地化文件中必须有相同的格式: DisplayName:RequiredPhoneNumber
+ //[DisplayName("DisplayName:RequiredPhoneNumber")] //两种方法都可以
+
+ // 如果Dto属性与本地化内容一致,不需要显示指定名称,但是本地化文件必须存在对应格式的文本: DisplayName:PhoneNumber
public string PhoneNumber { get; set; }
[Required]
@@ -20,6 +26,8 @@ namespace LINGYUN.Abp.Account
[Required]
[StringLength(6)]
- public string VerifyCode { get; set; }
+ [DisableAuditing]
+ [Display(Name = "DisplayName:SmsVerifyCode")]
+ public string Code { get; set; }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneRegisterCodeDto.cs
similarity index 75%
rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs
rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneRegisterCodeDto.cs
index 7ce34f592..29411035f 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneRegisterCodeDto.cs
@@ -4,14 +4,12 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account
{
- public class VerifyDto
+ public class SendPhoneRegisterCodeDto
{
[Required]
[Phone]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
+ [Display(Name = "PhoneNumber")]
public string PhoneNumber { get; set; }
-
- [Required]
- public PhoneNumberVerifyType VerifyType { get; set; }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneResetPasswordCodeDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneResetPasswordCodeDto.cs
new file mode 100644
index 000000000..f91daef98
--- /dev/null
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneResetPasswordCodeDto.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+using Volo.Abp.Identity;
+using Volo.Abp.Validation;
+
+namespace LINGYUN.Abp.Account
+{
+ public class SendPhoneResetPasswordCodeDto
+ {
+ [Required]
+ [Phone]
+ [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
+ [Display(Name = "PhoneNumber")]
+ public string PhoneNumber { get; set; }
+ }
+}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneSigninCodeDto.cs
similarity index 80%
rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs
rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneSigninCodeDto.cs
index 196ecce5a..a5113755f 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendPhoneSigninCodeDto.cs
@@ -4,11 +4,12 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account
{
- public class RegisterDto
+ public class SendPhoneSigninCodeDto
{
[Required]
[Phone]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
+ [Display(Name = "PhoneNumber")]
public string PhoneNumber { get; set; }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/WeChatRegisterDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/WeChatRegisterDto.cs
index 178ad11cd..9911d49ff 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/WeChatRegisterDto.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/WeChatRegisterDto.cs
@@ -8,22 +8,23 @@ namespace LINGYUN.Abp.Account
public class WeChatRegisterDto
{
[Required]
+ [DisableAuditing]
+ [Display(Name = "DisplayName:WeChatCode")]
public string Code { get; set; }
- [DisableAuditing]
[DataType(DataType.Password)]
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
+ [DisableAuditing]
+ [Display(Name = "Password")]
public string Password { get; set; }
- [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
- public string Name { get; set; }
-
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
+ [Display(Name = "UserName")]
public string UserName { get; set; }
- [EmailAddress]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
+ [Display(Name = "EmailAddress")]
public string EmailAddress { get; set; }
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs
index 25d36948a..c299db0a3 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs
@@ -1,17 +1,45 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
-using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
public interface IAccountAppService : IApplicationService
{
- Task RegisterAsync(PhoneNumberRegisterDto input);
-
- Task RegisterAsync(WeChatRegisterDto input);
-
- Task ResetPasswordAsync(PasswordResetDto input);
-
- Task VerifyPhoneNumberAsync(VerifyDto input);
+ ///
+ /// 通过手机号注册用户账户
+ ///
+ ///
+ ///
+ Task RegisterAsync(PhoneRegisterDto input);
+ ///
+ /// 通过微信注册用户账户
+ ///
+ ///
+ ///
+ Task RegisterAsync(WeChatRegisterDto input);
+ ///
+ /// 通过手机号重置用户密码
+ ///
+ ///
+ ///
+ Task ResetPasswordAsync(PhoneResetPasswordDto input);
+ ///
+ /// 发送手机注册验证码短信
+ ///
+ ///
+ ///
+ Task SendPhoneRegisterCodeAsync(SendPhoneRegisterCodeDto input);
+ ///
+ /// 发送手机登录验证码短信
+ ///
+ ///
+ ///
+ Task SendPhoneSigninCodeAsync(SendPhoneSigninCodeDto input);
+ ///
+ /// 发送手机重置密码验证码短信
+ ///
+ ///
+ ///
+ Task SendPhoneResetPasswordCodeAsync(SendPhoneResetPasswordCodeDto input);
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json
new file mode 100644
index 000000000..4027f88bd
--- /dev/null
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json
@@ -0,0 +1,15 @@
+{
+ "culture": "en",
+ "texts": {
+ "SendRepeatSmsVerifyCode": "Phone verification code cannot be sent repeatedly within {0} minutes!",
+ "DuplicatePhoneNumber": "The phone number already exists!",
+ "PhoneNumberNotRegisterd": "The registered mobile phone number is not registered!",
+ "InvalidSmsVerifyCode": "The phone verification code is invalid or expired!",
+ "RequiredEmailAddress": "Email address required",
+ "InvalidPhoneNumber": "Invalid phone number",
+ "DuplicateWeChat": "The wechat has been registered!",
+ "DisplayName:SmsVerifyCode": "SMS verification code",
+ "DisplayName:EmailVerifyCode": "Mail verification code",
+ "DisplayName:WeChatCode": "Wechat login code"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
new file mode 100644
index 000000000..61f172530
--- /dev/null
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
@@ -0,0 +1,15 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!",
+ "DuplicatePhoneNumber": "手机号已经存在!",
+ "PhoneNumberNotRegisterd": "手机号码未注册!",
+ "InvalidSmsVerifyCode": "手机验证码无效或已经过期!",
+ "RequiredEmailAddress": "邮件地址必须输入",
+ "InvalidPhoneNumber": "手机号无效",
+ "DuplicateWeChat": "微信号已经注册过!",
+ "DisplayName:SmsVerifyCode": "短信验证码",
+ "DisplayName:EmailVerifyCode": "邮件验证码",
+ "DisplayName:WeChatCode": "微信登录凭证"
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj
index 4fef853ca..9813dc753 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj
@@ -14,9 +14,9 @@
+
-
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs
index c765eb16e..4fe51cb5d 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs
@@ -1,12 +1,13 @@
-using LINGYUN.Abp.WeChat.Authorization;
+using LINGYUN.Abp.Identity;
+using LINGYUN.Abp.WeChat.Authorization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(
- typeof(AbpAccountDomainModule),
typeof(Volo.Abp.Account.AbpAccountApplicationModule),
typeof(AbpAccountApplicationContractsModule),
+ typeof(AbpIdentityDomainModule),
typeof(AbpWeChatAuthorizationModule))]
public class AbpAccountApplicationModule : AbpModule
{
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
index 938ceaa01..9f53e47e3 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
@@ -1,49 +1,58 @@
-using LINGYUN.Abp.WeChat.Authorization;
+using LINGYUN.Abp.Identity;
+using LINGYUN.Abp.Identity.Security;
+using LINGYUN.Abp.Identity.Settings;
+using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.Distributed;
using System;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
+using Volo.Abp.Account.Localization;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Identity;
using Volo.Abp.Settings;
-using Volo.Abp.Sms;
+using Volo.Abp.Validation;
+using IIdentityUserRepository = LINGYUN.Abp.Identity.IIdentityUserRepository;
namespace LINGYUN.Abp.Account
{
- ///
- /// 用户注册服务
- ///
public class AccountAppService : ApplicationService, IAccountAppService
{
- private IWeChatOpenIdFinder _weChatOpenIdFinder;
- protected IWeChatOpenIdFinder WeChatOpenIdFinder => LazyGetRequiredService(ref _weChatOpenIdFinder);
- protected ISmsSender SmsSender { get; }
- protected IdentityUserManager UserManager { get; }
+ protected ITotpService TotpService { get; }
protected IdentityUserStore UserStore { get; }
+ protected IdentityUserManager UserManager { get; }
protected IIdentityUserRepository UserRepository { get; }
- protected IDistributedCache Cache { get; }
- protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; }
+ protected IUserSecurityCodeSender SecurityCodeSender { get; }
+ protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; }
+
+ protected IDistributedCache SecurityTokenCache { get; }
+
public AccountAppService(
- ISmsSender smsSender,
- IdentityUserManager userManager,
+ ITotpService totpService,
IdentityUserStore userStore,
+ IdentityUserManager userManager,
+ IWeChatOpenIdFinder weChatOpenIdFinder,
IIdentityUserRepository userRepository,
- IDistributedCache cache,
- PhoneNumberTokenProvider phoneNumberTokenProvider)
+ IUserSecurityCodeSender securityCodeSender,
+ IDistributedCache securityTokenCache)
{
- Cache = cache;
- SmsSender = smsSender;
+ TotpService = totpService;
UserStore = userStore;
UserManager = userManager;
UserRepository = userRepository;
- PhoneNumberTokenProvider = phoneNumberTokenProvider;
- LocalizationResource = typeof(Localization.AccountResource);
+ WeChatOpenIdFinder = weChatOpenIdFinder;
+ SecurityCodeSender = securityCodeSender;
+ SecurityTokenCache = securityTokenCache;
+
+ LocalizationResource = typeof(AccountResource);
}
- public virtual async Task RegisterAsync(WeChatRegisterDto input)
+ public virtual async Task RegisterAsync(WeChatRegisterDto input)
{
+ ThowIfInvalidEmailAddress(input.EmailAddress);
await CheckSelfRegistrationAsync();
var wehchatOpenId = await WeChatOpenIdFinder.FindAsync(input.Code);
@@ -54,13 +63,19 @@ namespace LINGYUN.Abp.Account
// 应该要抛出微信号已注册异常,而不是直接返回注册用户数据,否则造成用户信息泄露
throw new UserFriendlyException(L["DuplicateWeChat"]);
}
- var userName = input.UserName ?? "wx-" + wehchatOpenId.OpenId;
- var userEmail = input.EmailAddress ?? $"{userName}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个
-
- user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id)
+ var userName = input.UserName;
+ if (userName.IsNullOrWhiteSpace())
+ {
+ userName = "wxid-" + wehchatOpenId.OpenId.ToMd5();
+ }
+
+ var userEmail = input.EmailAddress;//如果邮件地址不验证,随意写入一个
+ if (userEmail.IsNullOrWhiteSpace())
{
- Name = input.Name ?? userName
- };
+ userEmail = $"{userName}@{CurrentTenant.Name ?? "default"}.io";
+ }
+
+ user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id);
(await UserManager.CreateAsync(user, input.Password)).CheckErrors();
(await UserManager.AddDefaultRolesAsync(user)).CheckErrors();
@@ -68,205 +83,192 @@ namespace LINGYUN.Abp.Account
var userLogin = new UserLoginInfo(AbpWeChatAuthorizationConsts.ProviderKey, wehchatOpenId.OpenId, AbpWeChatAuthorizationConsts.DisplayName);
(await UserManager.AddLoginAsync(user, userLogin)).CheckErrors();
- return ObjectMapper.Map(user);
+ await CurrentUnitOfWork.SaveChangesAsync();
}
- ///
- /// 用户注册
- ///
- ///
- ///
- ///
- /// 用户通过VerifyPhoneNumber接口发送到手机的验证码,传递注册信息注册用户
- /// 如果没有此手机号的缓存记录或验证码不匹配,抛出验证码无效的异常
- /// 用户注册成功,清除缓存的验证码记录
- ///
- public virtual async Task RegisterAsync(PhoneNumberRegisterDto input)
+
+ public virtual async Task SendPhoneRegisterCodeAsync(SendPhoneRegisterCodeDto input)
{
- var phoneVerifyCacheKey = NormalizeCacheKey(input.PhoneNumber);
+ await CheckSelfRegistrationAsync();
+ await CheckNewUserPhoneNumberNotBeUsedAsync(input.PhoneNumber);
- var phoneVerifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey);
- if(phoneVerifyCacheItem == null || !phoneVerifyCacheItem.VerifyCode.Equals(input.VerifyCode))
+ var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
+ var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);
+ var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1);
+
+ if (securityTokenCacheItem != null)
{
- throw new UserFriendlyException(L["PhoneVerifyCodeInvalid"]);
+ throw new UserFriendlyException(L["SendRepeatSmsVerifyCode", interval]);
}
- await CheckSelfRegistrationAsync();
+ var template = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsNewUserRegister);
- // 需要用户输入邮箱?
- //if (UserManager.Options.User.RequireUniqueEmail)
- //{
- // if (input.EmailAddress.IsNullOrWhiteSpace())
- // {
- // throw new UserFriendlyException(L["RequiredEmailAddress"]);
- // }
- //}
-
- var userEmail = input.EmailAddress ?? $"{input.PhoneNumber}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个
- var userName = input.UserName ?? input.PhoneNumber;
- var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id)
- {
- Name = input.Name ?? input.PhoneNumber
- };
- // 写入手机号要在创建用户之前,因为有一个自定义的手机号验证
- await UserStore.SetPhoneNumberAsync(user, input.PhoneNumber);
- await UserStore.SetPhoneNumberConfirmedAsync(user, true);
+ // 安全令牌
+ var securityToken = GuidGenerator.Create().ToString("N");
- (await UserManager.CreateAsync(user, input.Password)).CheckErrors();
+ var code = TotpService.GenerateCode(Encoding.Unicode.GetBytes(securityToken), securityTokenCacheKey);
+ securityTokenCacheItem = new SmsSecurityTokenCacheItem(code.ToString(), securityToken);
- (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();
+ await SecurityCodeSender.SendPhoneConfirmedCodeAsync(
+ input.PhoneNumber, securityTokenCacheItem.Token, template);
- await Cache.RemoveAsync(phoneVerifyCacheKey);
-
- return ObjectMapper.Map(user);
+ await SecurityTokenCache
+ .SetAsync(securityTokenCacheKey, securityTokenCacheItem,
+ new DistributedCacheEntryOptions
+ {
+ AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(interval)
+ });
}
- // TODO: 是否有必要移动到ProfileService
- ///
- /// 重置用户密码
- ///
- ///
- ///
- public virtual async Task ResetPasswordAsync(PasswordResetDto passwordReset)
+ public virtual async Task RegisterAsync(PhoneRegisterDto input)
{
- // 本来可以不需要的,令牌算法有一个有效期
- // 不过这里采用令牌强制过期策略,避免一个令牌多次使用
- var phoneVerifyCacheKey = NormalizeCacheKey(passwordReset.PhoneNumber);
+ await CheckSelfRegistrationAsync();
+ await CheckNewUserPhoneNumberNotBeUsedAsync(input.PhoneNumber);
- var phoneVerifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey);
- if (phoneVerifyCacheItem == null || !phoneVerifyCacheItem.VerifyCode.Equals(passwordReset.VerifyCode))
+ var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
+ var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);
+ if (securityTokenCacheItem == null)
{
- throw new UserFriendlyException(L["PhoneVerifyCodeInvalid"]);
+ // 验证码过期
+ throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
}
- var userId = await GetUserIdByPhoneNumberAsync(passwordReset.PhoneNumber);
+ // 验证码是否有效
+ if (input.Code.Equals(securityTokenCacheItem.Token) && int.TryParse(input.Code, out int token))
+ {
+ var securityToken = Encoding.Unicode.GetBytes(securityTokenCacheItem.SecurityToken);
+ // 校验totp验证码
+ if (TotpService.ValidateCode(securityToken, token, securityTokenCacheKey))
+ {
+ var userEmail = input.EmailAddress ?? $"{input.PhoneNumber}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个
+ var userName = input.UserName ?? input.PhoneNumber;
+ var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id)
+ {
+ Name = input.Name ?? input.PhoneNumber
+ };
+
+ await UserStore.SetPhoneNumberAsync(user, input.PhoneNumber);
+ await UserStore.SetPhoneNumberConfirmedAsync(user, true);
- var user = await UserManager.GetByIdAsync(userId);
+ (await UserManager.CreateAsync(user, input.Password)).CheckErrors();
- (await UserManager.ResetPasswordAsync(user, phoneVerifyCacheItem.VerifyToken, passwordReset.NewPassword)).CheckErrors();
+ (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();
+ await SecurityTokenCache.RemoveAsync(securityTokenCacheKey);
- await Cache.RemoveAsync(phoneVerifyCacheKey);
+ await CurrentUnitOfWork.SaveChangesAsync();
+
+ return;
+ }
+ }
+ // 验证码无效
+ throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
}
- ///
- /// 验证手机号码
- ///
- ///
- ///
- ///
- /// 用户传递手机号码及认证类型
- /// 1、如果认证类型为注册:
- /// 先查询是否存在此手机号的缓存验证码信息,如果存在,抛出不能重复发送验证码异常
- /// 随机生成6位纯数字验证码,通过短信接口服务发送到用户手机,并缓存验证码,设定一个有效时长
- ///
- /// 2、如果认证类型为登录:
- /// 先查询是否存在此手机号的缓存验证码信息,如果存在,抛出不能重复发送验证码异常
- /// 通过手机号查询用户信息,如果用户不存在,抛出手机号未注册异常
- /// 调用PhoneNumberTokenProvider接口生成6位手机验证码,用途为 phone_verify
- /// 发送手机验证码到用户手机,并缓存验证码,设定一个有效时长
- ///
- /// 用户调用 IdentityServer4/connect/token 登录系统(需要引用LINGYUN.Abp.IdentityServer.SmsValidator模块)
- /// 参数1:grant_type=phone_verify
- /// 参数2:phone_number=手机号码
- /// 参数3:phone_verify_code=手机验证码
- /// 参数4:client_id=客户端标识
- /// 参数5:client_secret=客户端密钥
- ///
- public virtual async Task VerifyPhoneNumberAsync(VerifyDto input)
+
+ public virtual async Task SendPhoneResetPasswordCodeAsync(SendPhoneResetPasswordCodeDto input)
{
- // TODO: 借用TOTP算法生成6位动态验证码
+ /*
+ * 注解: 微软的重置密码方法通过 UserManager.GeneratePasswordResetTokenAsync 接口生成密码重置Token
+ * 而这个Token设计的意义就是用户通过链接来重置密码,所以不适合短信验证
+ * 某些企业是把链接生成一个短链发送短信的,不过这种方式不是很推荐,因为现在是真没几个人敢随便点短信链接的
+ *
+ * 此处设计方式为:
+ *
+ * step1: 例行检查是否重复发送,这一点是很有必要的
+ * step2: 通过已确认的手机号来查询用户,如果用户未确认手机号,那就不能发送,这一点也是很有必要的
+ * step3(重点): 通过 UserManager.GenerateTwoFactorTokenAsync 接口来生成二次认证码,这就相当于伪验证码,只是用于确认用户传递的验证码是否通过
+ * 比起自己生成随机数,这个验证码利用了TOTP算法,有时间限制的
+ * step4(重点): 用户传递验证码后,通过 UserManager.VerifyTwoFactorTokenAsync 接口来校验验证码
+ * 验证通过后,再利用 UserManager.GeneratePasswordResetTokenAsync 接口来生成真正的用于重置密码的Token
+ */
- var verifyCodeExpiration = await SettingProvider.GetAsync(AccountSettingNames.PhoneVerifyCodeExpiration);
- var phoneVerifyCacheKey = NormalizeCacheKey(input.PhoneNumber);
- var verifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey);
- if (verifyCacheItem != null)
+ var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
+ var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);
+ var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1);
+ // 传递 isConfirmed 用户必须是已确认过手机号的
+ var user = await GetUserByPhoneNumberAsync(input.PhoneNumber, isConfirmed: true);
+ // 能查询到缓存就是重复发送
+ if (securityTokenCacheItem != null)
{
- throw new UserFriendlyException(L["PhoneVerifyCodeNotRepeatSend", verifyCodeExpiration]);
+ throw new UserFriendlyException(L["SendRepeatSmsVerifyCode", interval]);
}
- verifyCacheItem = new AccountRegisterVerifyCacheItem
- {
- PhoneNumber = input.PhoneNumber,
- };
- switch (input.VerifyType)
- {
- case PhoneNumberVerifyType.Register:
- var phoneVerifyCode = new Random().Next(100000, 999999);
- verifyCacheItem.VerifyCode = phoneVerifyCode.ToString();
- var templateCode = await SettingProvider.GetOrDefaultAsync(AccountSettingNames.SmsRegisterTemplateCode, ServiceProvider);
- await SendPhoneVerifyMessageAsync(templateCode, input.PhoneNumber, phoneVerifyCode.ToString());
- break;
- case PhoneNumberVerifyType.Signin:
- var phoneSigninCode = await SendSigninVerifyCodeAsync(input.PhoneNumber);
- verifyCacheItem.VerifyCode = phoneSigninCode;
- break;
- case PhoneNumberVerifyType.ResetPassword:
- var resetPasswordCode = new Random().Next(100000, 999999);
- verifyCacheItem.VerifyCode = resetPasswordCode.ToString();
- var resetPasswordToken = await SendResetPasswordVerifyCodeAsync(input.PhoneNumber, verifyCacheItem.VerifyCode);
- verifyCacheItem.VerifyToken = resetPasswordToken;
- break;
- }
-
- var cacheOptions = new DistributedCacheEntryOptions
- {
- AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(verifyCodeExpiration)
- };
- await Cache.SetAsync(phoneVerifyCacheKey, verifyCacheItem, cacheOptions);
- }
- ///
- /// 发送登录验证码
- ///
- /// 手机号
- /// 返回登录验证码
- protected virtual async Task SendSigninVerifyCodeAsync(string phoneNumber)
- {
- // 查找用户信息
- var user = await GetUserByPhoneNumberAsync(phoneNumber);
- // 获取登录验证码模板号
- var templateCode = await SettingProvider.GetOrDefaultAsync(AccountSettingNames.SmsSigninTemplateCode, ServiceProvider);
- // 生成手机验证码
- var phoneVerifyCode = await PhoneNumberTokenProvider.GenerateAsync("phone_verify", UserManager, user);
+ var template = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsResetPassword);
+ // 生成二次认证码
+ var code = await UserManager.GenerateTwoFactorTokenAsync(user, TokenOptions.DefaultPhoneProvider);
// 发送短信验证码
- await SendPhoneVerifyMessageAsync(templateCode, user.PhoneNumber, phoneVerifyCode);
-
- return phoneVerifyCode;
+ await SecurityCodeSender.SendPhoneConfirmedCodeAsync(input.PhoneNumber, code, template);
+ // 缓存这个手机号的记录,防重复
+ securityTokenCacheItem = new SmsSecurityTokenCacheItem(code, user.SecurityStamp);
+ await SecurityTokenCache
+ .SetAsync(securityTokenCacheKey, securityTokenCacheItem,
+ new DistributedCacheEntryOptions
+ {
+ AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(interval)
+ });
}
-
- protected virtual async Task SendResetPasswordVerifyCodeAsync(string phoneNumber, string phoneVerifyCode)
+
+ public virtual async Task ResetPasswordAsync(PhoneResetPasswordDto input)
{
- // 查找用户信息
- var user = await GetUserByPhoneNumberAsync(phoneNumber);
- // 获取登录验证码模板号
- var templateCode = await SettingProvider.GetOrDefaultAsync(AccountSettingNames.SmsResetPasswordTemplateCode, ServiceProvider);
- // 生成重置密码验证码
- var phoneVerifyToken = await UserManager.GeneratePasswordResetTokenAsync(user);
- // 发送短信验证码
- await SendPhoneVerifyMessageAsync(templateCode, user.PhoneNumber, phoneVerifyCode);
+ var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
+ var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);
+ if (securityTokenCacheItem == null)
+ {
+ throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
+ }
+ // 传递 isConfirmed 用户必须是已确认过手机号的
+ var user = await GetUserByPhoneNumberAsync(input.PhoneNumber, isConfirmed: true);
+ // 验证二次认证码
+ if (!await UserManager.VerifyTwoFactorTokenAsync(user, TokenOptions.DefaultPhoneProvider, input.Code))
+ {
+ // 验证码无效
+ throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
+ }
+ // 生成真正的重置密码Token
+ var resetPwdToken = await UserManager.GeneratePasswordResetTokenAsync(user);
+ // 重置密码
+ (await UserManager.ResetPasswordAsync(user, resetPwdToken, input.NewPassword)).CheckErrors();
+ // 移除缓存项
+ await SecurityTokenCache.RemoveAsync(securityTokenCacheKey);
- return phoneVerifyToken;
+ await CurrentUnitOfWork.SaveChangesAsync();
}
- protected virtual async Task GetUserByPhoneNumberAsync(string phoneNumber)
+ public virtual async Task SendPhoneSigninCodeAsync(SendPhoneSigninCodeDto input)
{
- // 查找用户信息
- var user = await UserRepository.FindByPhoneNumberAsync(phoneNumber);
- if (user == null)
+ var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
+ var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);
+ var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1);
+ if (securityTokenCacheItem != null)
{
- throw new UserFriendlyException(L["PhoneNumberNotRegisterd"]);
+ throw new UserFriendlyException(L["SendRepeatSmsVerifyCode", interval]);
}
- return user;
+ // 传递 isConfirmed 验证过的用户才允许通过手机登录
+ var user = await GetUserByPhoneNumberAsync(input.PhoneNumber, isConfirmed: true);
+ var code = await UserManager.GenerateTwoFactorTokenAsync(user, TokenOptions.DefaultPhoneProvider);
+ var template = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsUserSignin);
+
+ // 发送登录验证码短信
+ await SecurityCodeSender.SendPhoneConfirmedCodeAsync(input.PhoneNumber, code, template);
+ // 缓存登录验证码状态,防止同一手机号重复发送
+ securityTokenCacheItem = new SmsSecurityTokenCacheItem(code, user.SecurityStamp);
+ await SecurityTokenCache
+ .SetAsync(securityTokenCacheKey, securityTokenCacheItem,
+ new DistributedCacheEntryOptions
+ {
+ AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(interval)
+ });
}
- protected virtual async Task GetUserIdByPhoneNumberAsync(string phoneNumber)
+ protected virtual async Task GetUserByPhoneNumberAsync(string phoneNumber, bool isConfirmed = true)
{
- // 查找用户信息
- var userId = await UserRepository.GetIdByPhoneNumberAsync(phoneNumber);
- if (!userId.HasValue)
+ var user = await UserRepository.FindByPhoneNumberAsync(phoneNumber, isConfirmed, true);
+ if (user == null)
{
throw new UserFriendlyException(L["PhoneNumberNotRegisterd"]);
}
- return userId.Value;
+ return user;
}
+
///
/// 检查是否允许用户注册
///
@@ -278,28 +280,26 @@ namespace LINGYUN.Abp.Account
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
}
}
- ///
- /// 发送短信验证码
- ///
- ///
- ///
- ///
- ///
- protected virtual async Task SendPhoneVerifyMessageAsync(string templateCode, string phoneNumber, string verifyCode)
+
+ protected virtual async Task CheckNewUserPhoneNumberNotBeUsedAsync(string phoneNumber)
{
- var sendMessage = new SmsMessage(phoneNumber, "SendSmsMessage");
- sendMessage.Properties.Add("code", verifyCode);
- sendMessage.Properties.Add("TemplateCode", templateCode);
- await SmsSender.SendAsync(sendMessage);
+ if (await UserRepository.IsPhoneNumberUedAsync(phoneNumber))
+ {
+ throw new UserFriendlyException(L["DuplicatePhoneNumber"]);
+ }
}
- ///
- /// 格式化缓存主键
- ///
- /// 手机号码
- ///
- protected string NormalizeCacheKey(string phoneNumber)
+
+ private void ThowIfInvalidEmailAddress(string inputEmail)
{
- return $"ACCOUNT-PHONE:{phoneNumber}";
+ if (!inputEmail.IsNullOrWhiteSpace() &&
+ !ValidationHelper.IsValidEmailAddress(inputEmail))
+ {
+ throw new AbpValidationException(
+ new ValidationResult[]
+ {
+ new ValidationResult(L["The {0} field is not a valid e-mail address.", L["DisplayName:EmailAddress"]], new string[]{ "EmailAddress" })
+ });
+ }
}
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj
index 671875157..f34d4b2d2 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj
@@ -1,4 +1,4 @@
-
+
@@ -8,17 +8,11 @@
-
-
-
-
-
-
-
+
-
+
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingDefinitionProvider.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingDefinitionProvider.cs
deleted file mode 100644
index d4e3ccf0b..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingDefinitionProvider.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using LINGYUN.Abp.Account.Localization;
-using Volo.Abp.Localization;
-using Volo.Abp.Settings;
-
-namespace LINGYUN.Abp.Account
-{
- public class AccountSettingDefinitionProvider : SettingDefinitionProvider
- {
- public override void Define(ISettingDefinitionContext context)
- {
-
- context.Add(GetAccountSettings());
- }
-
- protected SettingDefinition[] GetAccountSettings()
- {
- return new SettingDefinition[]
- {
- new SettingDefinition(
- name: AccountSettingNames.SmsRegisterTemplateCode,
- defaultValue: "SMS_190728520",
- displayName: L("DisplayName:SmsRegisterTemplateCode"),
- description: L("Description:SmsRegisterTemplateCode"),
- isVisibleToClients: true)
- .WithProviders(
- GlobalSettingValueProvider.ProviderName,
- TenantSettingValueProvider.ProviderName),
- new SettingDefinition(
- name: AccountSettingNames.SmsSigninTemplateCode,
- defaultValue: "SMS_190728516",
- displayName: L("DisplayName:SmsSigninTemplateCode"),
- description: L("Description:SmsSigninTemplateCode"),
- isVisibleToClients: true)
- .WithProviders(
- GlobalSettingValueProvider.ProviderName,
- TenantSettingValueProvider.ProviderName),
- new SettingDefinition(
- name: AccountSettingNames.SmsResetPasswordTemplateCode,
- defaultValue: "SMS_192530831",
- displayName: L("DisplayName:SmsResetPasswordTemplateCode"),
- description: L("Description:SmsResetPasswordTemplateCode"),
- isVisibleToClients: true)
- .WithProviders(
- GlobalSettingValueProvider.ProviderName,
- TenantSettingValueProvider.ProviderName),
- new SettingDefinition(
- name: AccountSettingNames.PhoneVerifyCodeExpiration,
- defaultValue: "3",
- displayName: L("DisplayName:PhoneVerifyCodeExpiration"),
- description: L("Description:PhoneVerifyCodeExpiration"),
- isVisibleToClients: true)
- .WithProviders(
- GlobalSettingValueProvider.ProviderName,
- TenantSettingValueProvider.ProviderName),
- };
- }
-
- protected LocalizableString L(string name)
- {
- return LocalizableString.Create(name);
- }
- }
-}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs
deleted file mode 100644
index b5599c281..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace LINGYUN.Abp.Account
-{
- public class AccountSettingNames
- {
- public const string GroupName = "Abp.Account";
- ///
- /// 短信验证码过期时间
- ///
- public const string PhoneVerifyCodeExpiration = GroupName + ".PhoneVerifyCodeExpiration";
- ///
- /// 用户注册短信验证码模板号
- ///
- public const string SmsRegisterTemplateCode = GroupName + ".SmsRegisterTemplateCode";
- ///
- /// 用户登录短信验证码模板号
- ///
- public const string SmsSigninTemplateCode = GroupName + ".SmsSigninTemplateCode";
- ///
- /// 用户重置密码短信验证码模板号
- ///
- public const string SmsResetPasswordTemplateCode = GroupName + ".SmsResetPasswordTemplateCode";
- }
-}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs
deleted file mode 100644
index c132a9b9b..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Volo.Abp.Localization;
-
-namespace LINGYUN.Abp.Account.Localization
-{
- [LocalizationResourceName("LINYUNAbpAccount")]
- public class AccountResource
- {
- }
-}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json
deleted file mode 100644
index 758961ad5..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "culture": "en",
- "texts": {
- "PhoneNumberNotRegisterd": "The registered mobile phone number is not registered!",
- "PhoneVerifyCodeInvalid": "The phone verification code is invalid or expired!",
- "PhoneVerifyCodeNotRepeatSend": "Phone verification code cannot be sent repeatedly within {0} minutes!",
- "DisplayName:SmsRegisterTemplateCode": "Register sms template",
- "Description:SmsRegisterTemplateCode": "When the user registers, he/she should send the template number of the SMS verification code and fill in the template number of the corresponding cloud platform registration",
- "DisplayName:SmsSigninTemplateCode": "Signin sms template",
- "Description:SmsSigninTemplateCode": "When the user logs in, he/she should send the template number of the SMS verification code and fill in the template number of the corresponding cloud platform registration",
- "DisplayName:SmsResetPasswordTemplateCode": "Reset password sms template",
- "Description:SmsResetPasswordTemplateCode": "When the user resets the password, he/she sends the template number of SMS verification code and fills in the template number registered on the cloud platform",
- "DisplayName:PhoneVerifyCodeExpiration": "SMS verification code validity",
- "Description:PhoneVerifyCodeExpiration": "The valid time for the user to send SMS verification code, unit m, default 3m",
- "RequiredEmailAddress": "Email address required",
- "InvalidPhoneNumber": "Invalid phone number",
- "DuplicatePhoneNumber": "The phone number {0} has been registered!",
- "DuplicateWeChat": "The wechat has been registered!"
- }
-}
\ No newline at end of file
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
deleted file mode 100644
index da45e2944..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "culture": "zh-Hans",
- "texts": {
- "PhoneNumberNotRegisterd": "手机号码未注册!",
- "PhoneVerifyCodeInvalid": "手机验证码无效或已经过期!",
- "PhoneVerifyCodeNotRepeatSend": "手机验证码不能在 {0} 分钟内重复发送!",
- "DisplayName:SmsRegisterTemplateCode": "用户注册短信模板",
- "Description:SmsRegisterTemplateCode": "用户注册时发送短信验证码的模板号,填写对应云平台注册的模板号",
- "DisplayName:SmsSigninTemplateCode": "用户登录短信模板",
- "Description:SmsSigninTemplateCode": "用户登录时发送短信验证码的模板号,填写对应云平台注册的模板号",
- "DisplayName:SmsResetPasswordTemplateCode": "用户重置密码短信模板",
- "Description:SmsResetPasswordTemplateCode": "用户重置密码时发送短信验证码的模板号,填写对应云平台注册的模板号",
- "DisplayName:PhoneVerifyCodeExpiration": "短信验证码有效期",
- "Description:PhoneVerifyCodeExpiration": "用户发送短信验证码的有效时长,单位m,默认3m",
- "RequiredEmailAddress": "邮件地址必须输入",
- "InvalidPhoneNumber": "手机号无效",
- "DuplicatePhoneNumber": "手机号已经注册过!",
- "DuplicateWeChat": "微信号已经注册过!"
- }
-}
\ No newline at end of file
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj
index 4381c4277..0272fba42 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs
deleted file mode 100644
index 31a2237b4..000000000
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/Microsoft/AspNetCore/Identity/PhoneNumberUserValidator.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using LINGYUN.Abp.Account.Localization;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Localization;
-using System;
-using System.Threading.Tasks;
-using Volo.Abp;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.Identity;
-using IIdentityUserRepository = LINGYUN.Abp.Account.IIdentityUserRepository;
-
-namespace Microsoft.AspNetCore.Identity
-{
- [Dependency(ServiceLifetime.Scoped, ReplaceServices = true)]
- [ExposeServices(typeof(IUserValidator))]
- public class PhoneNumberUserValidator : UserValidator
- {
- private readonly IStringLocalizer _stringLocalizer;
- private readonly IIdentityUserRepository _identityUserRepository;
-
- public PhoneNumberUserValidator(
- IStringLocalizer stringLocalizer,
- IIdentityUserRepository identityUserRepository)
- {
- _stringLocalizer = stringLocalizer;
- _identityUserRepository = identityUserRepository;
- }
- public override async Task ValidateAsync(UserManager manager, IdentityUser user)
- {
- await ValidatePhoneNumberAsync(manager, user);
- return await base.ValidateAsync(manager, user);
- }
-
- protected virtual async Task ValidatePhoneNumberAsync(UserManager manager, IdentityUser user)
- {
- var phoneNumber = await manager.GetPhoneNumberAsync(user);
- if (phoneNumber.IsNullOrWhiteSpace())
- {
- return;
- // 如果用户没有手机号,不验证
- //throw new UserFriendlyException(_stringLocalizer["InvalidPhoneNumber"].Value, "InvalidPhoneNumber");
- }
-
- var phoneNumberHasRegisted = await _identityUserRepository.PhoneNumberHasRegistedAsync(phoneNumber);
- if (phoneNumberHasRegisted)
- {
- throw new UserFriendlyException(_stringLocalizer["DuplicatePhoneNumber", phoneNumber].Value, "DuplicatePhoneNumber");
- }
- }
- }
-}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj
index 6ebc79af3..df3312e51 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs
index 9ed5a4bc3..66ae75ed2 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs
@@ -1,31 +1,27 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
-using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.Localization;
+using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(
typeof(AbpAccountApplicationContractsModule),
- typeof(AbpAspNetCoreMvcModule))]
+ typeof(Volo.Abp.Account.AbpAccountHttpApiModule))]
public class AbpAccountHttpApiModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
- PreConfigure(mvcBuilder =>
+ PreConfigure(options =>
{
- mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly);
+ options.AddAssemblyResource(typeof(AccountResource), typeof(AbpAccountApplicationContractsModule).Assembly);
+ // 原生的在Web项目指定,不没有引用Web项目的情况下需要它
+ options.AddAssemblyResource(typeof(AccountResource), typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule).Assembly);
});
- }
- public override void ConfigureServices(ServiceConfigurationContext context)
- {
- Configure(options =>
+ PreConfigure(mvcBuilder =>
{
- options.Resources
- .Get()
- .AddBaseTypes(typeof(AccountResource));
+ mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly);
});
}
}
diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs
index 55d4db76d..e223617e6 100644
--- a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs
+++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs
@@ -3,7 +3,6 @@ using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
@@ -21,30 +20,44 @@ namespace LINGYUN.Abp.Account
[HttpPost]
[Route("wechat/register")]
- public virtual async Task RegisterAsync(WeChatRegisterDto input)
+ public virtual async Task RegisterAsync(WeChatRegisterDto input)
{
- return await AccountAppService.RegisterAsync(input);
+ await AccountAppService.RegisterAsync(input);
}
[HttpPost]
[Route("phone/register")]
- public virtual async Task RegisterAsync(PhoneNumberRegisterDto input)
+ public virtual async Task RegisterAsync(PhoneRegisterDto input)
{
- return await AccountAppService.RegisterAsync(input);
+ await AccountAppService.RegisterAsync(input);
+ }
+
+ [HttpPut]
+ [Route("phone/reset-password")]
+ public virtual async Task ResetPasswordAsync(PhoneResetPasswordDto input)
+ {
+ await AccountAppService.ResetPasswordAsync(input);
}
[HttpPost]
- [Route("phone/verify")]
- public virtual async Task VerifyPhoneNumberAsync(VerifyDto input)
+ [Route("phone/send-signin-code")]
+ public virtual async Task SendPhoneSigninCodeAsync(SendPhoneSigninCodeDto input)
{
- await AccountAppService.VerifyPhoneNumberAsync(input);
+ await AccountAppService.SendPhoneSigninCodeAsync(input);
}
- [HttpPut]
- [Route("phone/reset-password")]
- public virtual async Task ResetPasswordAsync(PasswordResetDto passwordReset)
+ [HttpPost]
+ [Route("phone/send-register-code")]
+ public virtual async Task SendPhoneRegisterCodeAsync(SendPhoneRegisterCodeDto input)
+ {
+ await AccountAppService.SendPhoneRegisterCodeAsync(input);
+ }
+
+ [HttpPost]
+ [Route("phone/send-password-reset-code")]
+ public virtual async Task SendPhoneResetPasswordCodeAsync(SendPhoneResetPasswordCodeDto input)
{
- await AccountAppService.ResetPasswordAsync(passwordReset);
+ await AccountAppService.SendPhoneResetPasswordCodeAsync(input);
}
}
}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj
new file mode 100644
index 000000000..c0868d9c2
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj
@@ -0,0 +1,24 @@
+
+
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpAspNetCoreMvcValidationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpAspNetCoreMvcValidationModule.cs
new file mode 100644
index 000000000..7ebbfa1e9
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpAspNetCoreMvcValidationModule.cs
@@ -0,0 +1,31 @@
+using System;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.Validation.Localization;
+using Volo.Abp.VirtualFileSystem;
+
+namespace LINGYUN.Abp.AspNetCore.Mvc.Validation
+{
+ [Obsolete("用于测试模型绑定与验证相关的类,无需引用")]
+ [DependsOn(
+ typeof(AbpAspNetCoreMvcModule))]
+ public class AbpAspNetCoreMvcValidationModule : AbpModule
+ {
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Get()
+ .AddVirtualJson("/LINGYUN/Abp/AspNetCore/Mvc/Validation/Localization/MissingFields");
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpDataAnnotationsMetadataProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpDataAnnotationsMetadataProvider.cs
new file mode 100644
index 000000000..d0cbb3501
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.AspNetCore.Mvc.Validation/LINGYUN/Abp/AspNetCore/Mvc/Validation/AbpDataAnnotationsMetadataProvider.cs
@@ -0,0 +1,563 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.DataAnnotations;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
+using Microsoft.Extensions.Localization;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Reflection;
+
+
+namespace LINGYUN.Abp.AspNetCore.Mvc.Validation
+{
+ public class AbpDataAnnotationsMetadataProvider :
+ IBindingMetadataProvider,
+ IDisplayMetadataProvider,
+ IValidationMetadataProvider
+ {
+ // The [Nullable] attribute is synthesized by the compiler. It's best to just compare the type name.
+ private const string NullableAttributeFullTypeName = "System.Runtime.CompilerServices.NullableAttribute";
+ private const string NullableFlagsFieldName = "NullableFlags";
+
+ private const string NullableContextAttributeFullName = "System.Runtime.CompilerServices.NullableContextAttribute";
+ private const string NullableContextFlagsFieldName = "Flag";
+
+ private readonly IStringLocalizerFactory _stringLocalizerFactory;
+ private readonly MvcOptions _options;
+ private readonly MvcDataAnnotationsLocalizationOptions _localizationOptions;
+
+ public AbpDataAnnotationsMetadataProvider(
+ MvcOptions options,
+ IOptions localizationOptions,
+ IStringLocalizerFactory stringLocalizerFactory)
+ {
+ if (options == null)
+ {
+ throw new ArgumentNullException(nameof(options));
+ }
+
+ if (localizationOptions == null)
+ {
+ throw new ArgumentNullException(nameof(localizationOptions));
+ }
+
+ _options = options;
+ _localizationOptions = localizationOptions.Value;
+ _stringLocalizerFactory = stringLocalizerFactory;
+ }
+
+ ///
+ public void CreateBindingMetadata(BindingMetadataProviderContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ var editableAttribute = context.Attributes.OfType().FirstOrDefault();
+ if (editableAttribute != null)
+ {
+ context.BindingMetadata.IsReadOnly = !editableAttribute.AllowEdit;
+ }
+ }
+
+ ///
+ public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ var attributes = context.Attributes;
+ var dataTypeAttribute = attributes.OfType().FirstOrDefault();
+ var displayAttribute = attributes.OfType().FirstOrDefault();
+ var displayColumnAttribute = attributes.OfType().FirstOrDefault();
+ var displayFormatAttribute = attributes.OfType().FirstOrDefault();
+ var displayNameAttribute = attributes.OfType().FirstOrDefault();
+ var hiddenInputAttribute = attributes.OfType().FirstOrDefault();
+ var scaffoldColumnAttribute = attributes.OfType().FirstOrDefault();
+ var uiHintAttribute = attributes.OfType().FirstOrDefault();
+
+ // Special case the [DisplayFormat] attribute hanging off an applied [DataType] attribute. This property is
+ // non-null for DataType.Currency, DataType.Date, DataType.Time, and potentially custom [DataType]
+ // subclasses. The DataType.Currency, DataType.Date, and DataType.Time [DisplayFormat] attributes have a
+ // non-null DataFormatString and the DataType.Date and DataType.Time [DisplayFormat] attributes have
+ // ApplyFormatInEditMode==true.
+ if (displayFormatAttribute == null && dataTypeAttribute != null)
+ {
+ displayFormatAttribute = dataTypeAttribute.DisplayFormat;
+ }
+
+ var displayMetadata = context.DisplayMetadata;
+
+ // ConvertEmptyStringToNull
+ if (displayFormatAttribute != null)
+ {
+ displayMetadata.ConvertEmptyStringToNull = displayFormatAttribute.ConvertEmptyStringToNull;
+ }
+
+ // DataTypeName
+ if (dataTypeAttribute != null)
+ {
+ displayMetadata.DataTypeName = dataTypeAttribute.GetDataTypeName();
+ }
+ else if (displayFormatAttribute != null && !displayFormatAttribute.HtmlEncode)
+ {
+ displayMetadata.DataTypeName = nameof(DataType.Html);
+ }
+
+ var containerType = context.Key.ContainerType ?? context.Key.ModelType;
+ IStringLocalizer localizer = null;
+ if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
+ {
+ localizer = _localizationOptions.DataAnnotationLocalizerProvider(containerType, _stringLocalizerFactory);
+ }
+
+ // Description
+ if (displayAttribute != null)
+ {
+ if (localizer != null &&
+ !string.IsNullOrEmpty(displayAttribute.Description) &&
+ displayAttribute.ResourceType == null)
+ {
+ displayMetadata.Description = () => localizer[displayAttribute.Description];
+ }
+ else
+ {
+ displayMetadata.Description = () => displayAttribute.GetDescription();
+ }
+ }
+
+ // DisplayFormatString
+ if (displayFormatAttribute != null)
+ {
+ displayMetadata.DisplayFormatString = displayFormatAttribute.DataFormatString;
+ }
+
+ // DisplayName
+ // DisplayAttribute has precedence over DisplayNameAttribute.
+ if (displayAttribute?.GetName() != null)
+ {
+ if (localizer != null &&
+ !string.IsNullOrEmpty(displayAttribute.Name) &&
+ displayAttribute.ResourceType == null)
+ {
+ var displayName = localizer[displayAttribute.Name];
+ displayMetadata.DisplayName = () => displayName;
+ }
+ else
+ {
+ displayMetadata.DisplayName = () => displayAttribute.GetName();
+ }
+ }
+ else if (displayNameAttribute != null)
+ {
+ if (localizer != null &&
+ !string.IsNullOrEmpty(displayNameAttribute.DisplayName))
+ {
+ displayMetadata.DisplayName = () => localizer[displayNameAttribute.DisplayName];
+ }
+ else
+ {
+ displayMetadata.DisplayName = () => displayNameAttribute.DisplayName;
+ }
+ }
+
+ // EditFormatString
+ if (displayFormatAttribute != null && displayFormatAttribute.ApplyFormatInEditMode)
+ {
+ displayMetadata.EditFormatString = displayFormatAttribute.DataFormatString;
+ }
+
+ // IsEnum et cetera
+ var underlyingType = Nullable.GetUnderlyingType(context.Key.ModelType) ?? context.Key.ModelType;
+ var underlyingTypeInfo = underlyingType.GetTypeInfo();
+
+ if (underlyingTypeInfo.IsEnum)
+ {
+ // IsEnum
+ displayMetadata.IsEnum = true;
+
+ // IsFlagsEnum
+ displayMetadata.IsFlagsEnum = underlyingTypeInfo.IsDefined(typeof(FlagsAttribute), inherit: false);
+
+ // EnumDisplayNamesAndValues and EnumNamesAndValues
+ //
+ // Order EnumDisplayNamesAndValues by DisplayAttribute.Order, then by the order of Enum.GetNames().
+ // That method orders by absolute value, then its behavior is undefined (but hopefully stable).
+ // Add to EnumNamesAndValues in same order but Dictionary does not guarantee order will be preserved.
+
+ var groupedDisplayNamesAndValues = new List>();
+ var namesAndValues = new Dictionary();
+
+ IStringLocalizer enumLocalizer = null;
+ if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
+ {
+ enumLocalizer = _localizationOptions.DataAnnotationLocalizerProvider(underlyingType, _stringLocalizerFactory);
+ }
+
+ var enumFields = Enum.GetNames(underlyingType)
+ .Select(name => underlyingType.GetField(name))
+ .OrderBy(field => field.GetCustomAttribute(inherit: false)?.GetOrder() ?? 1000);
+
+ foreach (var field in enumFields)
+ {
+ var groupName = GetDisplayGroup(field);
+ var value = ((Enum)field.GetValue(obj: null)).ToString("d");
+
+ groupedDisplayNamesAndValues.Add(new KeyValuePair(
+ new EnumGroupAndName(
+ groupName,
+ () => GetDisplayName(field, enumLocalizer)),
+ value));
+ namesAndValues.Add(field.Name, value);
+ }
+
+ displayMetadata.EnumGroupedDisplayNamesAndValues = groupedDisplayNamesAndValues;
+ displayMetadata.EnumNamesAndValues = namesAndValues;
+ }
+
+ // HasNonDefaultEditFormat
+ if (!string.IsNullOrEmpty(displayFormatAttribute?.DataFormatString) &&
+ displayFormatAttribute?.ApplyFormatInEditMode == true)
+ {
+ // Have a non-empty EditFormatString based on [DisplayFormat] from our cache.
+ if (dataTypeAttribute == null)
+ {
+ // Attributes include no [DataType]; [DisplayFormat] was applied directly.
+ displayMetadata.HasNonDefaultEditFormat = true;
+ }
+ else if (dataTypeAttribute.DisplayFormat != displayFormatAttribute)
+ {
+ // Attributes include separate [DataType] and [DisplayFormat]; [DisplayFormat] provided override.
+ displayMetadata.HasNonDefaultEditFormat = true;
+ }
+ else if (dataTypeAttribute.GetType() != typeof(DataTypeAttribute))
+ {
+ // Attributes include [DisplayFormat] copied from [DataType] and [DataType] was of a subclass.
+ // Assume the [DataType] constructor used the protected DisplayFormat setter to override its
+ // default. That is derived [DataType] provided override.
+ displayMetadata.HasNonDefaultEditFormat = true;
+ }
+ }
+
+ // HideSurroundingHtml
+ if (hiddenInputAttribute != null)
+ {
+ displayMetadata.HideSurroundingHtml = !hiddenInputAttribute.DisplayValue;
+ }
+
+ // HtmlEncode
+ if (displayFormatAttribute != null)
+ {
+ displayMetadata.HtmlEncode = displayFormatAttribute.HtmlEncode;
+ }
+
+ // NullDisplayText
+ if (displayFormatAttribute != null)
+ {
+ displayMetadata.NullDisplayText = displayFormatAttribute.NullDisplayText;
+ }
+
+ // Order
+ if (displayAttribute?.GetOrder() != null)
+ {
+ displayMetadata.Order = displayAttribute.GetOrder().Value;
+ }
+
+ // Placeholder
+ if (displayAttribute != null)
+ {
+ if (localizer != null &&
+ !string.IsNullOrEmpty(displayAttribute.Prompt) &&
+ displayAttribute.ResourceType == null)
+ {
+ displayMetadata.Placeholder = () => localizer[displayAttribute.Prompt];
+ }
+ else
+ {
+ displayMetadata.Placeholder = () => displayAttribute.GetPrompt();
+ }
+ }
+
+ // ShowForDisplay
+ if (scaffoldColumnAttribute != null)
+ {
+ displayMetadata.ShowForDisplay = scaffoldColumnAttribute.Scaffold;
+ }
+
+ // ShowForEdit
+ if (scaffoldColumnAttribute != null)
+ {
+ displayMetadata.ShowForEdit = scaffoldColumnAttribute.Scaffold;
+ }
+
+ // SimpleDisplayProperty
+ if (displayColumnAttribute != null)
+ {
+ displayMetadata.SimpleDisplayProperty = displayColumnAttribute.DisplayColumn;
+ }
+
+ // TemplateHint
+ if (uiHintAttribute != null)
+ {
+ displayMetadata.TemplateHint = uiHintAttribute.UIHint;
+ }
+ else if (hiddenInputAttribute != null)
+ {
+ displayMetadata.TemplateHint = "HiddenInput";
+ }
+ }
+
+ ///
+ public void CreateValidationMetadata(ValidationMetadataProviderContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ // Read interface .Count once rather than per iteration
+ var contextAttributes = context.Attributes;
+ var contextAttributesCount = contextAttributes.Count;
+ var attributes = new List
-
+
diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs
index 95ddd848d..a5f265628 100644
--- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs
+++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs
@@ -3,7 +3,7 @@ using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
-using LINGYUN.Abp.Account;
+using LINGYUN.Abp.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@@ -25,8 +25,6 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
protected UserManager UserManager { get; }
protected SignInManager SignInManager { get; }
protected IStringLocalizer Localizer { get; }
- protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; }
-
public SmsTokenGrantValidator(
IEventService eventService,
@@ -34,7 +32,6 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
SignInManager signInManager,
IIdentityUserRepository userRepository,
IStringLocalizer stringLocalizer,
- PhoneNumberTokenProvider phoneNumberTokenProvider,
ILogger logger)
{
Logger = logger;
@@ -43,7 +40,6 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
SignInManager = signInManager;
Localizer = stringLocalizer;
UserRepository = userRepository;
- PhoneNumberTokenProvider = phoneNumberTokenProvider;
}
public string GrantType => SmsValidatorConsts.SmsValidatorGrantTypeName;
@@ -76,7 +72,8 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
Localizer["InvalidGrant:PhoneNumberNotRegister"]);
return;
}
- var validResult = await PhoneNumberTokenProvider.ValidateAsync(SmsValidatorConsts.SmsValidatorPurpose, phoneToken, UserManager, currentUser);
+
+ var validResult = await UserManager.VerifyTwoFactorTokenAsync(currentUser, TokenOptions.DefaultPhoneProvider, phoneToken);
if (!validResult)
{
Logger.LogWarning("Authentication failed for token: {0}, reason: invalid token", phoneToken);
@@ -85,6 +82,7 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
await EventService.RaiseAsync(new UserLoginFailureEvent(currentUser.UserName, $"invalid phone verify code {phoneToken}", false));
return;
}
+
var sub = await UserManager.GetUserIdAsync(currentUser);
var additionalClaims = new List();
@@ -95,6 +93,9 @@ namespace LINGYUN.Abp.IdentityServer.SmsValidator
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, phoneNumber, null));
context.Result = new GrantValidationResult(sub, OidcConstants.AuthenticationMethods.ConfirmationBySms, additionalClaims.ToArray());
+
+ // 登录之后需要更新安全令牌
+ (await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors();
}
}
}
diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
index e4950c4c3..600439192 100644
--- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
+++ b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
@@ -1,7 +1,8 @@
using DotNetCore.CAP;
-using LINGYUN.Abp.Account;
using LINGYUN.Abp.EventBus.CAP;
+using LINGYUN.Abp.Identity.EntityFrameworkCore;
using LINGYUN.Abp.IdentityServer;
+using LINGYUN.Abp.IdentityServer.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.PermissionManagement.Identity;
using LINYUN.Abp.Sms.Aliyun;
@@ -35,8 +36,6 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
-using Volo.Abp.Identity.EntityFrameworkCore;
-using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.IdentityServer.Jwt;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
@@ -52,7 +51,6 @@ using Volo.Abp.VirtualFileSystem;
namespace AuthServer.Host
{
[DependsOn(
- typeof(AbpAccountDomainModule),
typeof(AbpAccountWebIdentityServerModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
@@ -170,7 +168,7 @@ namespace AuthServer.Host
{
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
// 邮件登录地址
- options.Applications["MVC"].Urls[LINGYUN.Abp.Account.AccountUrlNames.MailLoginVerify] = "Account/VerifyCode";
+ options.Applications["MVC"].Urls["EmailVerifyLogin"] = "Account/VerifyCode";
});
context.Services.ConfigureNonBreakingSameSiteCookies();
diff --git a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj
index de3d68317..28b9b9d45 100644
--- a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj
+++ b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj
@@ -47,18 +47,17 @@
-
-
-
+
+
diff --git a/aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs b/aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
deleted file mode 100644
index 69727933e..000000000
--- a/aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
-using Volo.Abp.EntityFrameworkCore;
-using Volo.Abp.Identity;
-using Volo.Abp.Identity.EntityFrameworkCore;
-
-namespace AuthServer.Host.EntityFrameworkCore.Identity
-{
- public class EfCoreIdentityUserRepository : EfCoreRepository, LINGYUN.Abp.Account.IIdentityUserRepository,
- ITransientDependency
- {
- public EfCoreIdentityUserRepository(
- IDbContextProvider dbContextProvider)
- : base(dbContextProvider)
- {
- }
-
- public virtual async Task PhoneNumberHasRegistedAsync(string phoneNumber)
- {
- return await DbSet.AnyAsync(x => x.PhoneNumberConfirmed && x.PhoneNumber.Equals(phoneNumber));
- }
-
- public virtual async Task GetIdByPhoneNumberAsync(string phoneNumber)
- {
- return await DbSet
- .Where(x => x.PhoneNumber.Equals(phoneNumber))
- .Select(x => x.Id)
- .FirstOrDefaultAsync();
- }
-
- public virtual async Task FindByPhoneNumberAsync(string phoneNumber)
- {
- return await WithDetails()
- .Where(usr => usr.PhoneNumber.Equals(phoneNumber))
- .AsNoTracking()
- .FirstOrDefaultAsync();
- }
-
- public override IQueryable WithDetails()
- {
- return DbSet
- .Include(x => x.Claims)
- .Include(x => x.Roles)
- .Include(x => x.Logins)
- .Include(x => x.Tokens);
- }
- }
-}
diff --git a/aspnet-core/services/account/AuthServer.Host/Pages/Account/SendCode.cshtml.cs b/aspnet-core/services/account/AuthServer.Host/Pages/Account/SendCode.cshtml.cs
index 4d878ee94..bcee0841c 100644
--- a/aspnet-core/services/account/AuthServer.Host/Pages/Account/SendCode.cshtml.cs
+++ b/aspnet-core/services/account/AuthServer.Host/Pages/Account/SendCode.cshtml.cs
@@ -1,4 +1,5 @@
using AuthServer.Host.Emailing;
+using LINGYUN.Abp.Identity.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
@@ -100,8 +101,8 @@ namespace LINGYUN.Abp.Account.Web.Pages.Account
else if (Input.SelectedProvider == "Phone")
{
var phoneNumber = await UserManager.GetPhoneNumberAsync(user);
- var templateCode = await SettingProvider.GetOrNullAsync(AccountSettingNames.SmsSigninTemplateCode);
- Check.NotNullOrWhiteSpace(templateCode, nameof(AccountSettingNames.SmsSigninTemplateCode));
+ var templateCode = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsUserSignin);
+ Check.NotNullOrWhiteSpace(templateCode, nameof(IdentitySettingNames.User.SmsUserSignin));
// TODO: Ժչģ巢
var smsMessage = new SmsMessage(phoneNumber, code);
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs
index 75aa85d7e..42a04ffdf 100644
--- a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs
@@ -1,5 +1,4 @@
using DotNetCore.CAP;
-using IdentityModel;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing;
@@ -14,13 +13,11 @@ using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
using System.Text;
using Volo.Abp;
-using Volo.Abp.Account;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Security.Claims;
@@ -34,7 +31,6 @@ using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.Identity.Localization;
-using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
@@ -50,16 +46,14 @@ namespace LINGYUN.Abp.IdentityServer4
{
[DependsOn(
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
- typeof(LINGYUN.Abp.Identity.AbpIdentityHttpApiModule),
- typeof(LINGYUN.Abp.Identity.AbpIdentityApplicationModule),
typeof(LINGYUN.Abp.Account.AbpAccountApplicationModule),
typeof(LINGYUN.Abp.Account.AbpAccountHttpApiModule),
+ typeof(LINGYUN.Abp.Identity.AbpIdentityApplicationModule),
+ typeof(LINGYUN.Abp.Identity.AbpIdentityHttpApiModule),
typeof(LINGYUN.Abp.IdentityServer.AbpIdentityServerApplicationModule),
typeof(LINGYUN.Abp.IdentityServer.AbpIdentityServerHttpApiModule),
typeof(LINGYUN.Abp.Identity.EntityFrameworkCore.AbpIdentityEntityFrameworkCoreModule),
typeof(LINGYUN.Abp.IdentityServer.EntityFrameworkCore.AbpIdentityServerEntityFrameworkCoreModule),
- typeof(AbpAccountApplicationModule),
- typeof(AbpAccountHttpApiModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
@@ -180,7 +174,7 @@ namespace LINGYUN.Abp.IdentityServer4
// 滑动过期30天
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30);
// 绝对过期60天
- options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
+ options.GlobalCacheEntryOptions.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(60);
});
Configure(options =>
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl
new file mode 100644
index 000000000..157f51bb5
--- /dev/null
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl
@@ -0,0 +1,5 @@
+
+
{{L "EmailConfirmed" model.user}}
+
{{model.code}}
+
{{L "EmailConfirmedRemarks"}}
+
\ No newline at end of file
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs
new file mode 100644
index 000000000..4bda45557
--- /dev/null
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.Emailing.Templates;
+using Volo.Abp.Localization;
+using Volo.Abp.TextTemplating;
+using Volo.Abp.Identity.Localization;
+
+namespace LINGYUN.Abp.IdentityServer4.Emailing.Templates
+{
+ public class IdentityEmailTemplateDefinitionProvider : TemplateDefinitionProvider
+ {
+ public override void Define(ITemplateDefinitionContext context)
+ {
+ context.Add(
+ new TemplateDefinition(
+ IdentityEmailTemplates.EmailConfirmed,
+ displayName: LocalizableString.Create($"TextTemplate:{IdentityEmailTemplates.EmailConfirmed}"),
+ layout: StandardEmailTemplates.Layout,
+ localizationResource: typeof(IdentityResource)
+ ).WithVirtualFilePath("/LINGYUN/Abp/IdentityServer4/Emailing/Templates/EmailConfirmed.tpl", true)
+ );
+ }
+ }
+}
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs
new file mode 100644
index 000000000..3dab94dee
--- /dev/null
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs
@@ -0,0 +1,7 @@
+namespace LINGYUN.Abp.IdentityServer4.Emailing.Templates
+{
+ public static class IdentityEmailTemplates
+ {
+ public const string EmailConfirmed = "Abp.Identity.EmailConfirmed";
+ }
+}
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
deleted file mode 100644
index 99d394662..000000000
--- a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
-using Volo.Abp.EntityFrameworkCore;
-using Volo.Abp.Identity;
-using Volo.Abp.Identity.EntityFrameworkCore;
-
-namespace LINGYUN.Abp.IdentityServer4.Identity
-{
- public class EfCoreIdentityUserRepository : EfCoreRepository, Abp.Account.IIdentityUserRepository,
- ITransientDependency
- {
- public EfCoreIdentityUserRepository(
- IDbContextProvider dbContextProvider)
- : base(dbContextProvider)
- {
- }
-
- public virtual async Task PhoneNumberHasRegistedAsync(string phoneNumber)
- {
- return await DbSet.AnyAsync(x => x.PhoneNumberConfirmed && x.PhoneNumber.Equals(phoneNumber));
- }
-
- public virtual async Task GetIdByPhoneNumberAsync(string phoneNumber)
- {
- return await DbSet
- .Where(x => x.PhoneNumber.Equals(phoneNumber))
- .Select(x => x.Id)
- .FirstOrDefaultAsync();
- }
-
- public virtual async Task FindByPhoneNumberAsync(string phoneNumber)
- {
- return await DbSet.Where(usr => usr.PhoneNumber.Equals(phoneNumber))
- .AsNoTracking()
- .FirstOrDefaultAsync();
- }
- }
-}
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj
index d7759f7c0..7b13bf676 100644
--- a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj
@@ -11,6 +11,11 @@
+
+
+
+
+
@@ -61,4 +66,10 @@
+
+
+ Always
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Properties/launchSettings.json
index 408992e95..1585148ef 100644
--- a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Properties/launchSettings.json
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/Properties/launchSettings.json
@@ -1,7 +1,7 @@
-{
+{
"iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49612",
"sslPort": 0
@@ -10,11 +10,11 @@
"profiles": {
"LINGYUN.Abp.IdentityServer4.HttpApi.Host": {
"commandName": "Project",
- "launchBrowser": false,
- "applicationUrl": "http://127.0.0.1:30015",
"environmentVariables": {
+ "COMPlus_legacyCorruptedStateExceptionsPolicy": "1",
"ASPNETCORE_ENVIRONMENT": "Development"
- }
+ },
+ "applicationUrl": "http://127.0.0.1:30015"
}
}
-}
+}
\ No newline at end of file
diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/UserSecurityCodeSender.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/UserSecurityCodeSender.cs
new file mode 100644
index 000000000..7199a80f7
--- /dev/null
+++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/UserSecurityCodeSender.cs
@@ -0,0 +1,66 @@
+using LINGYUN.Abp.Identity;
+using LINGYUN.Abp.IdentityServer4.Emailing.Templates;
+using Microsoft.Extensions.Localization;
+using System.Threading;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Emailing;
+using Volo.Abp.Identity.Localization;
+using Volo.Abp.Sms;
+using Volo.Abp.TextTemplating;
+
+namespace LINGYUN.Abp.IdentityServer4
+{
+ public class UserSecurityCodeSender : IUserSecurityCodeSender, ITransientDependency
+ {
+ protected IEmailSender EmailSender { get; }
+ protected ITemplateRenderer TemplateRenderer { get; }
+ protected IStringLocalizer Localizer { get; }
+
+ protected ISmsSender SmsSender { get; }
+
+ public UserSecurityCodeSender(
+ ISmsSender smsSender,
+ IEmailSender emailSender,
+ ITemplateRenderer templateRenderer,
+ IStringLocalizer localizer)
+ {
+ SmsSender = smsSender;
+ EmailSender = emailSender;
+ TemplateRenderer = templateRenderer;
+ Localizer = localizer;
+ }
+
+ public virtual async Task SendEmailConfirmedCodeAsync(
+ string userName,
+ string email,
+ string token,
+ CancellationToken cancellation = default)
+ {
+ var emailContent = await TemplateRenderer.RenderAsync(
+ IdentityEmailTemplates.EmailConfirmed,
+ new { user = userName, code = token });
+
+ await EmailSender.SendAsync(
+ email,
+ Localizer["EmailConfirmed"],
+ emailContent);
+ }
+
+ public virtual async Task SendPhoneConfirmedCodeAsync(
+ string phone,
+ string token,
+ string template,
+ CancellationToken cancellation = default)
+ {
+ Check.NotNullOrWhiteSpace(template, nameof(template));
+
+ var smsMessage = new SmsMessage(phone, token);
+ smsMessage.Properties.Add("code", token);
+ smsMessage.Properties.Add("TemplateCode", template);
+
+ await SmsSender.SendAsync(smsMessage);
+ }
+ }
+}
diff --git a/vueJs/src/api/users.ts b/vueJs/src/api/users.ts
index 328e23d1b..5d329ffb0 100644
--- a/vueJs/src/api/users.ts
+++ b/vueJs/src/api/users.ts
@@ -169,13 +169,40 @@ export default class UserApiService {
})
}
- public static sendPhoneVerifyCode(phoneVerify: PhoneVerify) {
- const _url = '/api/account/phone/verify'
- return ApiService.HttpRequest({
+ /** 发送短信登录验证码 */
+ public static sendSmsSigninCode(phoneNumber: string) {
+ const _url = '/api/account/phone/send-signin-code'
+ return ApiService.HttpRequest({
baseURL: IdentityServiceUrl,
url: _url,
method: 'POST',
- data: phoneVerify
+ data: {
+ phoneNumber: phoneNumber
+ }
+ })
+ }
+
+ public static sendSmsResetPasswordCode(phoneNumber: string) {
+ const _url = '/api/account/phone/send-password-reset-code'
+ return ApiService.HttpRequest({
+ baseURL: IdentityServiceUrl,
+ url: _url,
+ method: 'POST',
+ data: {
+ phoneNumber: phoneNumber
+ }
+ })
+ }
+
+ public static sendSmsRegisterCode(phoneNumber: string) {
+ const _url = '/api/account/phone/send-register-code'
+ return ApiService.HttpRequest({
+ baseURL: IdentityServiceUrl,
+ url: _url,
+ method: 'POST',
+ data: {
+ phoneNumber: phoneNumber
+ }
})
}
diff --git a/vueJs/src/views/login/index.vue b/vueJs/src/views/login/index.vue
index 438015425..1a5b47043 100644
--- a/vueJs/src/views/login/index.vue
+++ b/vueJs/src/views/login/index.vue
@@ -157,7 +157,7 @@ import { Dictionary } from 'vue-router/types/router'
import TenantBox from '@/components/TenantBox/index.vue'
import LangSelect from '@/components/LangSelect/index.vue'
import { Component, Vue, Watch } from 'vue-property-decorator'
-import UserService, { PhoneVerify, VerifyType } from '@/api/users'
+import UserService from '@/api/users'
import { AbpModule } from '@/store/modules/abp'
@Component({
@@ -300,10 +300,7 @@ export default class extends Vue {
frmLogin.validateField('phoneNumber', (errorMsg: string) => {
if (!errorMsg) {
this.sending = true
- const phoneVerify = new PhoneVerify()
- phoneVerify.phoneNumber = this.loginForm.phoneNumber
- phoneVerify.verifyType = VerifyType.Signin
- UserService.sendPhoneVerifyCode(phoneVerify).then(() => {
+ UserService.sendSmsSigninCode(this.loginForm.phoneNumber).then(() => {
let interValTime = 60
const sendingName = this.l('login.afterSendVerifyCode')
const sendedName = this.l('login.sendVerifyCode')
diff --git a/vueJs/src/views/register/index.vue b/vueJs/src/views/register/index.vue
index fc6229b62..f031627f6 100644
--- a/vueJs/src/views/register/index.vue
+++ b/vueJs/src/views/register/index.vue
@@ -124,7 +124,7 @@ import { Dictionary } from 'vue-router/types/router'
import TenantBox from '@/components/TenantBox/index.vue'
import LangSelect from '@/components/LangSelect/index.vue'
import { Component, Vue, Watch } from 'vue-property-decorator'
-import UserService, { PhoneVerify, VerifyType, UserRegisterData } from '@/api/users'
+import UserService, { UserRegisterData } from '@/api/users'
import { AbpModule } from '@/store/modules/abp'
@Component({
@@ -246,10 +246,7 @@ export default class extends Vue {
frmLogin.validateField('phoneNumber', (errorMsg: string) => {
if (!errorMsg) {
this.sending = true
- const phoneVerify = new PhoneVerify()
- phoneVerify.phoneNumber = this.registerForm.phoneNumber
- phoneVerify.verifyType = VerifyType.Register
- UserService.sendPhoneVerifyCode(phoneVerify).then(() => {
+ UserService.sendSmsRegisterCode(this.registerForm.phoneNumber).then(() => {
let interValTime = 60
const sendingName = this.l('login.afterSendVerifyCode')
const sendedName = this.l('login.sendVerifyCode')
diff --git a/vueJs/src/views/reset-password/index.vue b/vueJs/src/views/reset-password/index.vue
index cd5030340..77e74949e 100644
--- a/vueJs/src/views/reset-password/index.vue
+++ b/vueJs/src/views/reset-password/index.vue
@@ -112,7 +112,7 @@ import { Dictionary } from 'vue-router/types/router'
import TenantBox from '@/components/TenantBox/index.vue'
import LangSelect from '@/components/LangSelect/index.vue'
import { Component, Vue, Watch } from 'vue-property-decorator'
-import UserService, { PhoneVerify, VerifyType, UserResetPasswordData } from '@/api/users'
+import UserService, { UserResetPasswordData } from '@/api/users'
import { AbpModule } from '@/store/modules/abp'
@Component({
@@ -226,10 +226,7 @@ export default class extends Vue {
frmResetPassword.validateField('phoneNumber', (errorMsg: string) => {
if (!errorMsg) {
this.sending = true
- const phoneVerify = new PhoneVerify()
- phoneVerify.phoneNumber = this.resetPasswordForm.phoneNumber
- phoneVerify.verifyType = VerifyType.ResetPassword
- UserService.sendPhoneVerifyCode(phoneVerify).then(() => {
+ UserService.sendSmsResetPasswordCode(this.resetPasswordForm.phoneNumber).then(() => {
let interValTime = 60
const sendingName = this.l('login.afterSendVerifyCode')
const sendedName = this.l('login.sendVerifyCode')