37 changed files with 333 additions and 271 deletions
@ -1,27 +1,11 @@ |
|||||
using Volo.Abp.Account.Localization; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp.Localization; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Account |
namespace LINGYUN.Abp.Account |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule))] |
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule), |
||||
|
typeof(AbpAccountDomainSharedModule))] |
||||
public class AbpAccountApplicationContractsModule : AbpModule |
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"); |
|
||||
}); |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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; } |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
@ -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" |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
{ |
|
||||
"culture": "zh-Hans", |
|
||||
"texts": { |
|
||||
"SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!", |
|
||||
"DuplicatePhoneNumber": "手机号已经存在!", |
|
||||
"PhoneNumberNotRegisterd": "手机号码未注册!", |
|
||||
"InvalidSmsVerifyCode": "手机验证码无效或已经过期!", |
|
||||
"RequiredEmailAddress": "邮件地址必须输入", |
|
||||
"InvalidPhoneNumber": "手机号无效", |
|
||||
"DuplicateWeChat": "微信号已经注册过!", |
|
||||
"DisplayName:SmsVerifyCode": "短信验证码", |
|
||||
"DisplayName:EmailVerifyCode": "邮件验证码", |
|
||||
"DisplayName:WeChatCode": "微信登录凭证" |
|
||||
} |
|
||||
} |
|
||||
@ -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> |
||||
@ -1,18 +1,25 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<Import Project="..\..\..\common.props" /> |
|
||||
|
|
||||
<PropertyGroup> |
<Import Project="..\..\..\configureawait.props" /> |
||||
<TargetFramework>netstandard2.0</TargetFramework> |
<Import Project="..\..\..\common.props" /> |
||||
<RootNamespace /> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<ItemGroup> |
<PropertyGroup> |
||||
<PackageReference Include="Volo.Abp.Localization" Version="4.4.0" /> |
<TargetFramework>netstandard2.0</TargetFramework> |
||||
</ItemGroup> |
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<ProjectReference Include="..\..\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj" /> |
<None Remove="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" /> |
||||
</ItemGroup> |
<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> |
</Project> |
||||
|
|||||
@ -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; } |
|
||||
} |
|
||||
} |
|
||||
@ -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; } = ""; |
|
||||
} |
|
||||
} |
|
||||
@ -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 |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Account.Emailing; |
||||
|
|
||||
|
public interface IAccountEmailVerifySender |
||||
|
{ |
||||
|
Task SendMailLoginVerifyCodeAsync( |
||||
|
string code, |
||||
|
string userName, |
||||
|
string emailAddress); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Account.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("AbpAccountResource")] |
||||
|
public class AbpAccountResource |
||||
|
{ |
||||
|
} |
||||
@ -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" |
||||
|
} |
||||
|
} |
||||
@ -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": "点击进行验证" |
||||
|
} |
||||
|
} |
||||
@ -1,9 +0,0 @@ |
|||||
namespace LINGYUN.Abp.Account |
|
||||
{ |
|
||||
public enum PhoneNumberVerifyType : sbyte |
|
||||
{ |
|
||||
Register = 0, |
|
||||
Signin = 10, |
|
||||
ResetPassword = 20 |
|
||||
} |
|
||||
} |
|
||||
@ -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; |
|
||||
} |
|
||||
} |
|
||||
@ -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); |
|
||||
} |
|
||||
@ -1,18 +1,5 @@ |
|||||
{ |
{ |
||||
"culture": "en", |
"culture": "en", |
||||
"texts": { |
"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" |
|
||||
} |
} |
||||
} |
} |
||||
@ -1,18 +1,5 @@ |
|||||
{ |
{ |
||||
"culture": "zh-Hans", |
"culture": "zh-Hans", |
||||
"texts": { |
"texts": { |
||||
"TwoFactor": "双因素身份验证", |
|
||||
"SelectedProvider": "选择验证方式", |
|
||||
"SendVerifyCode": "发送验证码", |
|
||||
"VerifyCode": "验证码", |
|
||||
"VerifyAuthenticatorCode": "验证身份代码", |
|
||||
"RememberBrowser": "在浏览器中记住我", |
|
||||
"TwoFactorAuthenticationInvaidUser": "认证失败,您的会话已失效,请程序登录!", |
|
||||
"InvaidGenerateTwoFactorToken": "验证码生成失败,请联系管理员!", |
|
||||
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件安全验证模板", |
|
||||
"MailSecurityVerify": "邮件安全验证", |
|
||||
"VerifyMyEmailAddress": "您好<br/><p>您此次邮件安全验证码如下,请输入验证码进行下一步操作。</p><p>如非你本人操作,请忽略此邮件。</p>", |
|
||||
"MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。", |
|
||||
"ClickToValidation": "点击进行验证" |
|
||||
} |
} |
||||
} |
} |
||||
Loading…
Reference in new issue