Browse Source

Improve two-factor certification

resolve [#130](https://github.com/colinin/abp-next-admin/issues/130)
pull/625/head
cKey 3 years ago
parent
commit
9f4bf86434
  1. 9
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 10
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj
  3. 22
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs
  4. 10
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/GetTwoFactorProvidersInput.cs
  5. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendEmailSigninCodeDto.cs
  6. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs
  7. 15
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json
  8. 15
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
  9. 39
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
  10. 2
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyClaimAppService.cs
  11. 30
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xsd
  12. 33
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj
  13. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs
  14. 9
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs
  15. 16
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountUrlNames.cs
  16. 44
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/AccountEmailVerifySender.cs
  17. 11
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs
  18. 9
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs
  19. 0
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs
  20. 0
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl
  21. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AbpAccountResource.cs
  22. 33
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json
  23. 33
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
  24. 9
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs
  25. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs
  26. 15
      aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs
  27. 104
      aspnet-core/services/LY.MicroService.identityServer/Emailing/AccountEmailVerifySender.cs
  28. 17
      aspnet-core/services/LY.MicroService.identityServer/Emailing/IAccountEmailVerifySender.cs
  29. 2
      aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs
  30. 2
      aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs
  31. 2
      aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj
  32. 13
      aspnet-core/services/LY.MicroService.identityServer/Localization/Resources/en.json
  33. 13
      aspnet-core/services/LY.MicroService.identityServer/Localization/Resources/zh-Hans.json
  34. 7
      aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendCode.cshtml
  35. 13
      aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendCode.cshtml.cs
  36. 3
      aspnet-core/services/LY.MicroService.identityServer/Pages/Account/VerifyAuthenticatorCode.cshtml
  37. 7
      aspnet-core/services/LY.MicroService.identityServer/Pages/Account/VerifyCode.cshtml

9
aspnet-core/LINGYUN.MicroService.All.sln

@ -426,7 +426,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Common", "modules\common\LINGYUN.Abp.Notifications.Common\LINGYUN.Abp.Notifications.Common.csproj", "{0CE035CF-2D8A-4559-93EC-ADBEC4237C61}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AspNetCore.Mvc.Localization", "modules\localization\LINGYUN.Abp.AspNetCore.Mvc.Localization\LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj", "{995DB1CE-A2FC-4468-A521-4207FD587EC5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Localization", "modules\localization\LINGYUN.Abp.AspNetCore.Mvc.Localization\LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj", "{995DB1CE-A2FC-4468-A521-4207FD587EC5}"
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", "{446852ED-D80C-450F-8383-6B1ADCA08A59}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -1110,6 +1112,10 @@ Global
{995DB1CE-A2FC-4468-A521-4207FD587EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.Build.0 = Release|Any CPU
{446852ED-D80C-450F-8383-6B1ADCA08A59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{446852ED-D80C-450F-8383-6B1ADCA08A59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{446852ED-D80C-450F-8383-6B1ADCA08A59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{446852ED-D80C-450F-8383-6B1ADCA08A59}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1319,6 +1325,7 @@ Global
{A53FE09E-6B1C-46C0-9422-C313D14AE9E4} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F}
{0CE035CF-2D8A-4559-93EC-ADBEC4237C61} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E}
{995DB1CE-A2FC-4468-A521-4207FD587EC5} = {90E88EAC-4291-4406-8D88-EFDF61B11292}
{446852ED-D80C-450F-8383-6B1ADCA08A59} = {9E72FEB9-A626-4312-892B-CDD043879758}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}

10
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj

@ -9,17 +9,11 @@
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
<PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="$(VoloAbpPackageVersion)" />
<ProjectReference Include="..\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj" />
</ItemGroup>
</Project>

22
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs

@ -1,27 +1,11 @@
using Volo.Abp.Account.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule))]
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule),
typeof(AbpAccountDomainSharedModule))]
public class AbpAccountApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountApplicationContractsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AccountResource>()
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources");
});
}
}
}

10
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/GetTwoFactorProvidersInput.cs

@ -0,0 +1,10 @@
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account;
public class GetTwoFactorProvidersInput
{
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
public string UserName { get; set; }
}

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendEmailSigninCodeDto.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.Account;
public class SendEmailSigninCodeDto
{
[Required]
[EmailAddress]
[Display(Name = "EmailAddress")]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
public string EmailAddress { get; set; }
}

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs

@ -1,4 +1,6 @@
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.Account
@ -35,11 +37,23 @@ namespace LINGYUN.Abp.Account
/// <param name="input"></param>
/// <returns></returns>
Task SendPhoneSigninCodeAsync(SendPhoneSigninCodeDto input);
/// <summary>
/// 发送邮件登录验证码
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task SendEmailSigninCodeAsync(SendEmailSigninCodeDto input);
/// <summary>
/// 发送手机重置密码验证码短信
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task SendPhoneResetPasswordCodeAsync(SendPhoneResetPasswordCodeDto input);
/// <summary>
/// 获取用户二次认证提供者列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task<ListResultDto<NameValue>> GetTwoFactorProvidersAsync(GetTwoFactorProvidersInput input);
}
}

15
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json

@ -1,15 +0,0 @@
{
"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"
}
}

15
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json

@ -1,15 +0,0 @@
{
"culture": "zh-Hans",
"texts": {
"SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!",
"DuplicatePhoneNumber": "手机号已经存在!",
"PhoneNumberNotRegisterd": "手机号码未注册!",
"InvalidSmsVerifyCode": "手机验证码无效或已经过期!",
"RequiredEmailAddress": "邮件地址必须输入",
"InvalidPhoneNumber": "手机号无效",
"DuplicateWeChat": "微信号已经注册过!",
"DisplayName:SmsVerifyCode": "短信验证码",
"DisplayName:EmailVerifyCode": "邮件验证码",
"DisplayName:WeChatCode": "微信登录凭证"
}
}

39
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs

@ -1,4 +1,5 @@
using LINGYUN.Abp.Identity;
using LINGYUN.Abp.Account.Emailing;
using LINGYUN.Abp.Identity;
using LINGYUN.Abp.Identity.Security;
using LINGYUN.Abp.Identity.Settings;
using LINGYUN.Abp.WeChat;
@ -10,10 +11,12 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Caching;
using Volo.Abp.Clients;
using Volo.Abp.Identity;
@ -304,6 +307,40 @@ namespace LINGYUN.Abp.Account
});
}
public async virtual Task SendEmailSigninCodeAsync(SendEmailSigninCodeDto input)
{
var sender = LazyServiceProvider.LazyGetRequiredService<IAccountEmailVerifySender>();
var user = await UserManager.FindByEmailAsync(input.EmailAddress);
if (user == null)
{
throw new UserFriendlyException(L["UserNotRegisterd"]);
}
if (!user.EmailConfirmed)
{
throw new UserFriendlyException(L["UserEmailNotConfirmed"]);
}
var code = await UserManager.GenerateTwoFactorTokenAsync(user, TokenOptions.DefaultEmailProvider);
await sender.SendMailLoginVerifyCodeAsync(code, user.UserName, user.Email);
}
public async virtual Task<ListResultDto<NameValue>> GetTwoFactorProvidersAsync(GetTwoFactorProvidersInput input)
{
var user = await UserManager.FindByNameAsync(input.UserName);
if (user == null)
{
throw new UserFriendlyException(L["UserNotRegisterd"]);
}
var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(user);
return new ListResultDto<NameValue>(
userFactors.Select(key => new NameValue(L[$"TwoFactor:{key}"].Value, key)).ToList());
}
protected virtual async Task<IdentityUser> GetUserByPhoneNumberAsync(string phoneNumber, bool isConfirmed = true)
{
var user = await UserRepository.FindByPhoneNumberAsync(phoneNumber, isConfirmed, true);

2
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyClaimAppService.cs

@ -1,4 +1,5 @@
using LINGYUN.Abp.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Security.Claims;
@ -6,6 +7,7 @@ using System.Threading.Tasks;
namespace LINGYUN.Abp.Account
{
[Authorize]
public class MyClaimAppService : AccountApplicationServiceBase, IMyClaimAppService
{
public MyClaimAppService()

30
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

33
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj

@ -1,18 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="4.4.0" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" />
<None Remove="LINGYUN\Abp\Account\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" />
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
</Project>

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs

@ -1,11 +1,13 @@
using Volo.Abp.Account.Localization;
using LINGYUN.Abp.Account.Localization;
using Volo.Abp.Emailing;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account
{
[DependsOn(typeof(AbpLocalizationModule))]
[DependsOn(
typeof(AbpEmailingModule))]
public class AbpAccountDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
@ -18,7 +20,7 @@ namespace LINGYUN.Abp.Account
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AccountResource>("zh-Hans")
.Add<AbpAccountResource>("en")
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources");
});
}

9
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs

@ -1,9 +0,0 @@
namespace LINGYUN.Abp.Account
{
public class AccountRegisterVerifyCacheItem
{
public string PhoneNumber { get; set; }
public string VerifyCode { get; set; }
public string VerifyToken { get; set; }
}
}

16
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountUrlNames.cs

@ -1,16 +0,0 @@
namespace LINGYUN.Abp.Account
{
/// <summary>
/// 定义账户系统Url
/// </summary>
/// <remarks>
/// 定义在领域共享层,可以方便其他应用程序调用
/// </remarks>
public static class AccountUrlNames
{
/// <summary>
/// 邮件登录验证地址
/// </summary>
public static string MailLoginVerify { get; set; } = "";
}
}

44
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/AccountEmailVerifySender.cs

@ -0,0 +1,44 @@
using LINGYUN.Abp.Account.Localization;
using LY.MicroService.IdentityServer.Emailing.Templates;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
using Volo.Abp.TextTemplating;
namespace LINGYUN.Abp.Account.Emailing;
public class AccountEmailVerifySender : IAccountEmailVerifySender, ITransientDependency
{
protected IEmailSender EmailSender { get; }
protected ITemplateRenderer TemplateRenderer { get; }
protected IStringLocalizer<AbpAccountResource> StringLocalizer { get; }
public AccountEmailVerifySender(
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IStringLocalizer<AbpAccountResource> stringLocalizer)
{
EmailSender = emailSender;
TemplateRenderer = templateRenderer;
StringLocalizer = stringLocalizer;
}
public async virtual Task SendMailLoginVerifyCodeAsync(
string code,
string userName,
string emailAddress)
{
var emailContent = await TemplateRenderer.RenderAsync(
AccountEmailTemplates.MailSecurityVerifyLink,
new { code = code, user = userName }
);
await EmailSender.SendAsync(
emailAddress,
StringLocalizer["MailSecurityVerify"],
emailContent
);
}
}

11
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs

@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.Account.Emailing;
public interface IAccountEmailVerifySender
{
Task SendMailLoginVerifyCodeAsync(
string code,
string userName,
string emailAddress);
}

9
aspnet-core/services/LY.MicroService.identityServer/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs → aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs

@ -1,4 +1,4 @@
using Volo.Abp.Account.Localization;
using LINGYUN.Abp.Account.Localization;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Localization;
using Volo.Abp.TextTemplating;
@ -12,10 +12,11 @@ public class AccountEmailTemplateDefinitionProvider : TemplateDefinitionProvider
context.Add(
new TemplateDefinition(
AccountEmailTemplates.MailSecurityVerifyLink,
displayName: LocalizableString.Create<AccountResource>($"TextTemplate:{AccountEmailTemplates.MailSecurityVerifyLink}"),
displayName: LocalizableString.Create<AbpAccountResource>(
$"TextTemplate:{AccountEmailTemplates.MailSecurityVerifyLink}"),
layout: StandardEmailTemplates.Layout,
localizationResource: typeof(AccountResource)
).WithVirtualFilePath("/Emailing/Templates/MailSecurityVerify.tpl", true)
localizationResource: typeof(AbpAccountResource)
).WithVirtualFilePath("/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl", true)
);
}
}

0
aspnet-core/services/LY.MicroService.identityServer/Emailing/Templates/AccountEmailTemplates.cs → aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs

0
aspnet-core/services/LY.MicroService.identityServer/Emailing/Templates/MailSecurityVerify.tpl → aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AbpAccountResource.cs

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Account.Localization;
[LocalizationResourceName("AbpAccountResource")]
public class AbpAccountResource
{
}

33
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json

@ -0,0 +1,33 @@
{
"culture": "en",
"texts": {
"UserNotRegisterd": "The user account is not registered!",
"UserEmailNotConfirmed": "The user's email address is not confirmed!",
"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",
"TwoFactor": "Two factor authentication",
"TwoFactor:Email": "Email",
"TwoFactor:Phone": "Phone",
"TwoFactor:Authenticator": "Authenticator",
"SelectedProvider": "Select validation mode",
"SendVerifyCode": "Send verification code",
"VerifyCode": "Verification code",
"VerifyAuthenticatorCode": "Authentication code",
"RememberBrowser": "Remember me in the browser",
"TwoFactorAuthenticationInvaidUser": "Authentication failed. Your session is invalid. Please re login try again!",
"InvaidGenerateTwoFactorToken": "Verification code generation failed. Please contact your administrator!",
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "Mail security validation template",
"MailSecurityVerify": "Mail security verification",
"VerifyMyEmailAddress": "Hello {0}<br/><p>Your email security verification code is as follows. Please enter the verification code to proceed to the next step.</p><p>If not operated by you, please ignore this email.</p>",
"MailSecurityVerifyRemarks": "<p>(If it is not in the form of a link, copy the address to the browser address bar for further access)</p><p>Thank you for your visit and have a good time!</p>",
"ClickToValidation": "Click link verification"
}
}

33
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json

@ -0,0 +1,33 @@
{
"culture": "zh-Hans",
"texts": {
"UserNotRegisterd": "用户账号未注册!",
"UserEmailNotConfirmed": "用户邮件地址未确认!",
"SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!",
"DuplicatePhoneNumber": "手机号已经存在!",
"PhoneNumberNotRegisterd": "手机号码未注册!",
"InvalidSmsVerifyCode": "手机验证码无效或已经过期!",
"RequiredEmailAddress": "邮件地址必须输入",
"InvalidPhoneNumber": "手机号无效",
"DuplicateWeChat": "微信号已经注册过!",
"DisplayName:SmsVerifyCode": "短信验证码",
"DisplayName:EmailVerifyCode": "邮件验证码",
"DisplayName:WeChatCode": "微信登录凭证",
"TwoFactor": "双因素身份验证",
"TwoFactor:Email": "邮箱验证",
"TwoFactor:Phone": "手机验证",
"TwoFactor:Authenticator": "验证码验证",
"SelectedProvider": "选择验证方式",
"SendVerifyCode": "发送验证码",
"VerifyCode": "验证码",
"VerifyAuthenticatorCode": "验证身份代码",
"RememberBrowser": "在浏览器中记住我",
"TwoFactorAuthenticationInvaidUser": "认证失败,您的会话已失效,请程序登录!",
"InvaidGenerateTwoFactorToken": "验证码生成失败,请联系管理员!",
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件安全验证模板",
"MailSecurityVerify": "邮件安全验证",
"VerifyMyEmailAddress": "您好<br/><p>您此次邮件安全验证码如下,请输入验证码进行下一步操作。</p><p>如非你本人操作,请忽略此邮件。</p>",
"MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。",
"ClickToValidation": "点击进行验证"
}
}

9
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs

@ -1,9 +0,0 @@
namespace LINGYUN.Abp.Account
{
public enum PhoneNumberVerifyType : sbyte
{
Register = 0,
Signin = 10,
ResetPassword = 20
}
}

14
aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs

@ -1,6 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
using LINGYUN.Abp.Account.Localization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
@ -24,5 +26,15 @@ namespace LINGYUN.Abp.Account
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AccountResource>()
.AddBaseTypes(typeof(AbpAccountResource));
});
}
}
}

15
aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.Account
@ -46,6 +47,13 @@ namespace LINGYUN.Abp.Account
await AccountAppService.SendPhoneSigninCodeAsync(input);
}
[HttpPost]
[Route("email/send-signin-code")]
public async virtual Task SendEmailSigninCodeAsync(SendEmailSigninCodeDto input)
{
await AccountAppService.SendEmailSigninCodeAsync(input);
}
[HttpPost]
[Route("phone/send-register-code")]
public async virtual Task SendPhoneRegisterCodeAsync(SendPhoneRegisterCodeDto input)
@ -59,5 +67,12 @@ namespace LINGYUN.Abp.Account
{
await AccountAppService.SendPhoneResetPasswordCodeAsync(input);
}
[HttpGet]
[Route("two-factor-providers")]
public async virtual Task<ListResultDto<NameValue>> GetTwoFactorProvidersAsync(GetTwoFactorProvidersInput input)
{
return await AccountAppService.GetTwoFactorProvidersAsync(input);
}
}
}

104
aspnet-core/services/LY.MicroService.identityServer/Emailing/AccountEmailVerifySender.cs

@ -1,104 +0,0 @@
using LY.MicroService.IdentityServer.Emailing.Templates;
using Microsoft.Extensions.Localization;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Web;
using Volo.Abp.Account.Emailing;
using Volo.Abp.Account.Localization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.TextTemplating;
using Volo.Abp.UI.Navigation.Urls;
namespace LY.MicroService.IdentityServer.Emailing;
[Dependency(ReplaceServices = true)]
[ExposeServices(
typeof(IAccountEmailer),
typeof(AccountEmailer),
typeof(IAccountEmailVerifySender),
typeof(AccountEmailVerifySender))]
public class AccountEmailVerifySender : AccountEmailer, IAccountEmailVerifySender, ITransientDependency
{
public AccountEmailVerifySender(
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IStringLocalizer<AccountResource> stringLocalizer,
IAppUrlProvider appUrlProvider,
ICurrentTenant currentTenant)
: base(emailSender, templateRenderer, stringLocalizer, appUrlProvider, currentTenant)
{
}
public virtual async Task SendMailLoginVerifyLinkAsync(
IdentityUser user,
string code,
string appName,
string provider,
bool rememberMe = false,
string returnUrl = null,
string returnUrlHash = null)
{
Debug.Assert(CurrentTenant.Id == user.TenantId, "This method can only work for current tenant!");
// TODO: 需要生成快捷链接
//var url = await AppUrlProvider.GetUrlAsync(appName, AccountUrlNames.MailLoginVerify);
//var link = $"{url}?provider={provider}&rememberMe={rememberMe}&resetToken={UrlEncoder.Default.Encode(code)}";
//if (!returnUrl.IsNullOrEmpty())
//{
// link += "&returnUrl=" + NormalizeReturnUrl(returnUrl);
//}
//if (!returnUrlHash.IsNullOrEmpty())
//{
// link += "&returnUrlHash=" + returnUrlHash;
//}
var emailContent = await TemplateRenderer.RenderAsync(
AccountEmailTemplates.MailSecurityVerifyLink,
new { code = code, user = user.UserName }
);
await EmailSender.SendAsync(
user.Email,
StringLocalizer["MailSecurityVerify"],
emailContent
);
}
protected override string NormalizeReturnUrl(string returnUrl)
{
if (returnUrl.IsNullOrEmpty())
{
return returnUrl;
}
//Handling openid connect login
if (returnUrl.StartsWith("/connect/authorize/callback", StringComparison.OrdinalIgnoreCase))
{
if (returnUrl.Contains("?"))
{
var queryPart = returnUrl.Split('?')[1];
var queryParameters = queryPart.Split('&');
foreach (var queryParameter in queryParameters)
{
if (queryParameter.Contains("="))
{
var queryParam = queryParameter.Split('=');
if (queryParam[0] == "redirect_uri")
{
return HttpUtility.UrlDecode(queryParam[1]);
}
}
}
}
}
return returnUrl;
}
}

17
aspnet-core/services/LY.MicroService.identityServer/Emailing/IAccountEmailVerifySender.cs

@ -1,17 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.Account.Emailing;
using Volo.Abp.Identity;
namespace LY.MicroService.IdentityServer.Emailing;
public interface IAccountEmailVerifySender : IAccountEmailer
{
Task SendMailLoginVerifyLinkAsync(
IdentityUser user,
string code,
string appName,
string provider,
bool rememberMe = false,
string returnUrl = null,
string returnUrlHash = null);
}

2
aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs

@ -1,4 +1,5 @@
using DotNetCore.CAP;
using LINGYUN.Abp.Account.Localization;
using LINGYUN.Abp.IdentityServer.IdentityResources;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.Serilog.Enrichers.Application;
@ -179,6 +180,7 @@ public partial class IdentityServerModule
options.Resources
.Get<AccountResource>()
.AddBaseTypes(typeof(AbpAccountResource))
.AddVirtualJson("/Localization/Resources");
});

2
aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs

@ -1,4 +1,5 @@
using DotNetCore.CAP;
using LINGYUN.Abp.Account;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.Data.DbMigrator;
@ -44,6 +45,7 @@ namespace LY.MicroService.IdentityServer;
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAccountWebIdentityServerModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountDomainSharedModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),

2
aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj

@ -7,7 +7,6 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Emailing\Templates\MailSecurityVerify.tpl" />
<EmbeddedResource Include="Localization\Resources\*.json" />
</ItemGroup>
@ -46,6 +45,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\account\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj" />
<ProjectReference Include="..\..\modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" />
<ProjectReference Include="..\..\modules\authorization\LINGYUN.Abp.Identity.OrganizaztionUnits\LINGYUN.Abp.Identity.OrganizaztionUnits.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" />

13
aspnet-core/services/LY.MicroService.identityServer/Localization/Resources/en.json

@ -1,18 +1,5 @@
{
"culture": "en",
"texts": {
"TwoFactor": "Two factor authentication",
"SelectedProvider": "Select validation mode",
"SendVerifyCode": "Send verification code",
"VerifyCode": "Verification code",
"VerifyAuthenticatorCode": "Authentication code",
"RememberBrowser": "Remember me in the browser",
"TwoFactorAuthenticationInvaidUser": "Authentication failed. Your session is invalid. Please re login try again!",
"InvaidGenerateTwoFactorToken": "Verification code generation failed. Please contact your administrator!",
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "Mail security validation template",
"MailSecurityVerify": "Mail security verification",
"VerifyMyEmailAddress": "Hello {0}<br/><p>Your email security verification code is as follows. Please enter the verification code to proceed to the next step.</p><p>If not operated by you, please ignore this email.</p>",
"MailSecurityVerifyRemarks": "<p>(If it is not in the form of a link, copy the address to the browser address bar for further access)</p><p>Thank you for your visit and have a good time!</p>",
"ClickToValidation": "Click link verification"
}
}

13
aspnet-core/services/LY.MicroService.identityServer/Localization/Resources/zh-Hans.json

@ -1,18 +1,5 @@
{
"culture": "zh-Hans",
"texts": {
"TwoFactor": "双因素身份验证",
"SelectedProvider": "选择验证方式",
"SendVerifyCode": "发送验证码",
"VerifyCode": "验证码",
"VerifyAuthenticatorCode": "验证身份代码",
"RememberBrowser": "在浏览器中记住我",
"TwoFactorAuthenticationInvaidUser": "认证失败,您的会话已失效,请程序登录!",
"InvaidGenerateTwoFactorToken": "验证码生成失败,请联系管理员!",
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件安全验证模板",
"MailSecurityVerify": "邮件安全验证",
"VerifyMyEmailAddress": "您好<br/><p>您此次邮件安全验证码如下,请输入验证码进行下一步操作。</p><p>如非你本人操作,请忽略此邮件。</p>",
"MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。",
"ClickToValidation": "点击进行验证"
}
}

7
aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendCode.cshtml

@ -14,7 +14,12 @@
<div class="form-group">
<abp-select asp-for="Input.SelectedProvider" label="@L["SelectedProvider"].Value" asp-items="@Model.Providers"></abp-select>
</div>
<abp-button type="submit" button-type="Primary" class="btn-block btn-lg mt-3">@L["SendVerifyCode"]</abp-button>
<div class="d-grid gap-2">
<abp-button type="submit" button-type="Primary" class="mt-2 mb-3">@L["SendVerifyCode"]</abp-button>
</div>
<a asp-page="./Login" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["Login"]
</a>
</form>
</div>
</div>

13
aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendCode.cshtml.cs

@ -1,4 +1,4 @@
using LY.MicroService.IdentityServer.Emailing;
using LINGYUN.Abp.Account.Emailing;
using LINGYUN.Abp.Identity.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
@ -9,7 +9,7 @@ using Volo.Abp;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Sms;
namespace LY.MicroService.IdentityServer.Pages.Account
{
public class SendCodeModel : AccountPageModel
@ -91,12 +91,11 @@ namespace LY.MicroService.IdentityServer.Pages.Account
if (Input.SelectedProvider == "Email")
{
var appName = "MVC"; // TODO: 跟随Abp框架的意思变动
await AccountEmailVerifySender
.SendMailLoginVerifyLinkAsync(
user, code, appName,
Input.SelectedProvider,
RememberMe, ReturnUrl, ReturnUrlHash);
.SendMailLoginVerifyCodeAsync(
code,
user.UserName,
user.Email);
}
else if (Input.SelectedProvider == "Phone")
{

3
aspnet-core/services/LY.MicroService.identityServer/Pages/Account/VerifyAuthenticatorCode.cshtml

@ -18,6 +18,9 @@
<abp-input asp-for="RememberBrowser" />
</div>
<abp-button type="submit" button-type="Primary" class="btn-block btn-lg mt-3">@L["VerifyAuthenticatorCode"]</abp-button>
<a asp-page="./Login" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["Login"]
</a>
</form>
</div>
</div>

7
aspnet-core/services/LY.MicroService.identityServer/Pages/Account/VerifyCode.cshtml

@ -18,7 +18,12 @@
<abp-input asp-for="Input.RememberBrowser" label="@L["RememberBrowser"].Value" />
</abp-column>
</abp-row>
<abp-button type="submit" button-type="Primary" class="btn-block btn-lg mt-3">@L["VerifyAuthenticatorCode"]</abp-button>
<div class="d-grid gap-2">
<abp-button type="submit" button-type="Primary" class="mt-2 mb-3">@L["VerifyAuthenticatorCode"]</abp-button>
</div>
<a asp-page="./SendCode" asp-all-route-data="@(new Dictionary<string, string> {{"returnUrl", Model.ReturnUrl}, {"returnUrlHash", Model.ReturnUrlHash}})">
<i class="fa fa-long-arrow-left"></i> @L["SendVerifyCode"]
</a>
</form>
</div>
</div>

Loading…
Cancel
Save