Browse Source
- Add the view of modifying password during login - Add modification of password authentication policy for temporary storage of sessions - Change the name of the contributor to the personal information pagepull/1220/head
9 changed files with 549 additions and 2 deletions
@ -0,0 +1,6 @@ |
|||||
|
namespace LINGYUN.Abp.Account.Web; |
||||
|
|
||||
|
public static class AbpAccountAuthenticationTypes |
||||
|
{ |
||||
|
public const string ShouldChangePassword = "Abp.Account.ShouldChangePassword"; |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Account.Web.Bundling; |
||||
|
|
||||
|
[DependsOn(typeof(JQueryScriptContributor))] |
||||
|
public class ChangePasswordScriptContributor : BundleContributor |
||||
|
{ |
||||
|
public override Task ConfigureBundleAsync(BundleConfigurationContext context) |
||||
|
{ |
||||
|
context.Files.Add("/Pages/Account/ChangePassword.js"); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
@page |
||||
|
@using Volo.Abp.Account.Localization |
||||
|
@using Volo.Abp.Identity |
||||
|
@using Volo.Abp.Users |
||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using LINGYUN.Abp.Account.Web.Bundling; |
||||
|
@using LINGYUN.Abp.Account.Web.Pages.Account |
||||
|
@inject IHtmlLocalizer<AccountResource> L |
||||
|
@model LINGYUN.Abp.Account.Web.Pages.Account.ChangePasswordModel |
||||
|
|
||||
|
<div class="card mt-3 shadow-sm rounded"> |
||||
|
<div class="card-body p-5"> |
||||
|
<h4>@L["ChangePassword"]</h4> |
||||
|
<form id="ChangePasswordForm" method="post"> |
||||
|
<div class="mb-3"> |
||||
|
@if (!Model.HideOldPasswordInput) |
||||
|
{ |
||||
|
<label asp-for="Input.CurrentPassword" class="form-label"></label> |
||||
|
<div class="input-group"> |
||||
|
<input type="password" class="form-control" autocomplete="new-password" maxlength="@IdentityUserConsts.MaxPasswordLength" asp-for="Input.CurrentPassword" /> |
||||
|
<button class="btn btn-secondary password-visibility-button" type="button"><i class="fa fa-eye-slash" aria-hidden="true"></i></button> |
||||
|
</div> |
||||
|
<span asp-validation-for="Input.CurrentPassword"></span> |
||||
|
|
||||
|
<br /> |
||||
|
} |
||||
|
<label asp-for="Input.NewPassword" class="form-label"></label> |
||||
|
<div class="input-group"> |
||||
|
<input type="password" class="form-control" autocomplete="new-password" maxlength="@IdentityUserConsts.MaxPasswordLength" asp-for="Input.NewPassword" /> |
||||
|
<button class="btn btn-secondary password-visibility-button" type="button"><i class="fa fa-eye-slash" aria-hidden="true"></i></button> |
||||
|
</div> |
||||
|
<span asp-validation-for="Input.NewPassword"></span><br /> |
||||
|
|
||||
|
<label asp-for="Input.NewPasswordConfirm" class="form-label"></label> |
||||
|
<div class="input-group"> |
||||
|
<input type="password" class="form-control" autocomplete="new-password" maxlength="@IdentityUserConsts.MaxPasswordLength" asp-for="Input.NewPasswordConfirm" /> |
||||
|
<button class="btn btn-secondary password-visibility-button" type="button"><i class="fa fa-eye-slash" aria-hidden="true"></i></button> |
||||
|
</div> |
||||
|
<span asp-validation-for="Input.NewPasswordConfirm"></span> |
||||
|
</div> |
||||
|
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value" /> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<abp-script-bundle name="@AccountBundles.Scripts.ChangePassword" /> |
||||
@ -0,0 +1,169 @@ |
|||||
|
using Microsoft.AspNetCore.Authentication; |
||||
|
using Microsoft.AspNetCore.Identity; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Security.Principal; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Account.Web.Pages.Account; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.Identity.AspNetCore; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Account.Web.Pages.Account; |
||||
|
|
||||
|
public class UserInfoModel : IMultiTenant |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
} |
||||
|
|
||||
|
public class ChangePasswordInputModel |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))] |
||||
|
[Display(Name = "DisplayName:CurrentPassword")] |
||||
|
[DataType(DataType.Password)] |
||||
|
[DisableAuditing] |
||||
|
public string CurrentPassword { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))] |
||||
|
[Display(Name = "DisplayName:NewPassword")] |
||||
|
[DataType(DataType.Password)] |
||||
|
[DisableAuditing] |
||||
|
public string NewPassword { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))] |
||||
|
[Display(Name = "DisplayName:NewPasswordConfirm")] |
||||
|
[DataType(DataType.Password)] |
||||
|
[DisableAuditing] |
||||
|
public string NewPasswordConfirm { get; set; } |
||||
|
} |
||||
|
|
||||
|
public class ChangePasswordModel : AccountPageModel |
||||
|
{ |
||||
|
[BindProperty] |
||||
|
public UserInfoModel UserInfo { get; set; } |
||||
|
|
||||
|
[BindProperty] |
||||
|
public ChangePasswordInputModel Input { get; set; } |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string ReturnUrl { get; set; } |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public string ReturnUrlHash { get; set; } |
||||
|
|
||||
|
[BindProperty(SupportsGet = true)] |
||||
|
public bool RememberMe { get; set; } |
||||
|
|
||||
|
public bool HideOldPasswordInput { get; set; } |
||||
|
|
||||
|
public AbpSignInManager AbpSignInManager => LazyServiceProvider.LazyGetRequiredService<AbpSignInManager>(); |
||||
|
public IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache => LazyServiceProvider.LazyGetRequiredService<IdentityDynamicClaimsPrincipalContributorCache>(); |
||||
|
|
||||
|
public async virtual Task<IActionResult> OnGetAsync() |
||||
|
{ |
||||
|
Input = new ChangePasswordInputModel(); |
||||
|
UserInfo = await GetCurrentUser(); |
||||
|
|
||||
|
if (UserInfo == null || UserInfo.TenantId != CurrentTenant.Id) |
||||
|
{ |
||||
|
await HttpContext.SignOutAsync(AbpAccountAuthenticationTypes.ShouldChangePassword); |
||||
|
return RedirectToPage("/Login", new { ReturnUrl, ReturnUrlHash }); |
||||
|
} |
||||
|
|
||||
|
HideOldPasswordInput = (await UserManager.GetByIdAsync(UserInfo.Id)).PasswordHash == null; |
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<IActionResult> OnPostAsync() |
||||
|
{ |
||||
|
if (Input.CurrentPassword == Input.NewPassword) |
||||
|
{ |
||||
|
Alerts.Warning(L["NewPasswordSameAsOld"]); |
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
var userInfo = await GetCurrentUser(); |
||||
|
if (userInfo != null) |
||||
|
{ |
||||
|
if (userInfo.TenantId == CurrentTenant.Id) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await IdentityOptions.SetAsync(); |
||||
|
var user = await UserManager.GetByIdAsync(userInfo.Id); |
||||
|
if (user.PasswordHash == null) |
||||
|
{ |
||||
|
(await UserManager.AddPasswordAsync(user, Input.NewPassword)).CheckErrors(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
(await UserManager.ChangePasswordAsync(user, Input.CurrentPassword, Input.NewPassword)).CheckErrors(); |
||||
|
} |
||||
|
|
||||
|
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() |
||||
|
{ |
||||
|
Identity = IdentitySecurityLogIdentityConsts.Identity, |
||||
|
Action = IdentitySecurityLogActionConsts.ChangePassword |
||||
|
}); |
||||
|
user.SetShouldChangePasswordOnNextLogin(false); |
||||
|
(await UserManager.UpdateAsync(user)).CheckErrors(); |
||||
|
|
||||
|
await HttpContext.SignOutAsync(AbpAccountAuthenticationTypes.ShouldChangePassword); |
||||
|
|
||||
|
await SignInManager.SignInAsync(user, RememberMe); |
||||
|
|
||||
|
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() |
||||
|
{ |
||||
|
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, |
||||
|
Action = IdentitySecurityLogActionConsts.LoginSucceeded, |
||||
|
UserName = user.UserName |
||||
|
}); |
||||
|
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId); |
||||
|
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Alerts.Warning(GetLocalizeExceptionMessage(ex)); |
||||
|
return Page(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await HttpContext.SignOutAsync(AbpAccountAuthenticationTypes.ShouldChangePassword); |
||||
|
|
||||
|
return RedirectToPage("/Login", new { ReturnUrl, ReturnUrlHash }); |
||||
|
} |
||||
|
|
||||
|
protected async virtual Task<UserInfoModel> GetCurrentUser() |
||||
|
{ |
||||
|
var result = await HttpContext.AuthenticateAsync(AbpAccountAuthenticationTypes.ShouldChangePassword); |
||||
|
|
||||
|
var userId = result?.Principal?.FindUserId(); |
||||
|
if (!userId.HasValue) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var tenantId = result.Principal.FindTenantId(); |
||||
|
using (CurrentTenant.Change(tenantId, null)) |
||||
|
{ |
||||
|
var identityUser = await UserManager.FindByIdAsync(userId.Value.ToString()); |
||||
|
return identityUser == null |
||||
|
? null |
||||
|
: new UserInfoModel() |
||||
|
{ |
||||
|
Id = identityUser.Id, |
||||
|
TenantId = identityUser.TenantId |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
$(function () { |
||||
|
$(".password-visibility-button").click(function (e) { |
||||
|
let button = $(this); |
||||
|
let passwordInput = button.parent().find("input"); |
||||
|
if (!passwordInput) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (passwordInput.attr("type") === "password") { |
||||
|
passwordInput.attr("type", "text"); |
||||
|
} |
||||
|
else { |
||||
|
passwordInput.attr("type", "password"); |
||||
|
} |
||||
|
|
||||
|
let icon = button.find("i"); |
||||
|
if (icon) { |
||||
|
icon.toggleClass("fa-eye-slash").toggleClass("fa-eye"); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,92 @@ |
|||||
|
@page |
||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using Volo.Abp.Account.Localization |
||||
|
@using Volo.Abp.Account.Settings |
||||
|
@using Volo.Abp.Account.Web.Pages.Account; |
||||
|
@using Volo.Abp.AspNetCore.Mvc.UI.Theming; |
||||
|
@using Volo.Abp.Identity; |
||||
|
@using Volo.Abp.Settings |
||||
|
@model LINGYUN.Abp.Account.Web.Pages.Account.LoginModel |
||||
|
@inject IHtmlLocalizer<AccountResource> L |
||||
|
@inject IThemeManager ThemeManager |
||||
|
@inject Volo.Abp.Settings.ISettingProvider SettingProvider |
||||
|
|
||||
|
@{ |
||||
|
Layout = ThemeManager.CurrentTheme.GetAccountLayout(); |
||||
|
} |
||||
|
|
||||
|
@section scripts |
||||
|
{ |
||||
|
<abp-script-bundle name="@typeof(LoginModel).FullName"> |
||||
|
<abp-script src="/Pages/Account/Login.js" /> |
||||
|
</abp-script-bundle> |
||||
|
} |
||||
|
|
||||
|
<div class="card mt-3 shadow-sm rounded"> |
||||
|
<div class="card-body p-5"> |
||||
|
<h4>@L["Login"]</h4> |
||||
|
@if (await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled)) |
||||
|
{ |
||||
|
<strong> |
||||
|
@L["AreYouANewUser"] |
||||
|
<a href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})" class="text-decoration-none">@L["Register"]</a> |
||||
|
</strong> |
||||
|
} |
||||
|
@if (Model.EnableLocalLogin) |
||||
|
{ |
||||
|
<form method="post" class="mt-4"> |
||||
|
<div class="mb-3"> |
||||
|
<label asp-for="LoginInput.UserNameOrEmailAddress" class="form-label"></label> |
||||
|
<input asp-for="LoginInput.UserNameOrEmailAddress" class="form-control" /> |
||||
|
<span asp-validation-for="LoginInput.UserNameOrEmailAddress" class="text-danger"></span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="mb-3"> |
||||
|
<label asp-for="LoginInput.Password" class="form-label"></label> |
||||
|
<div class="input-group"> |
||||
|
<input type="password" class="form-control" autocomplete="new-password" maxlength="@IdentityUserConsts.MaxPasswordLength" asp-for="LoginInput.Password" /> |
||||
|
<button class="btn btn-secondary" type="button" id="PasswordVisibilityButton"><i class="fa fa-eye-slash" aria-hidden="true"></i></button> |
||||
|
</div> |
||||
|
<span asp-validation-for="LoginInput.Password"></span> |
||||
|
</div> |
||||
|
<abp-row> |
||||
|
<abp-column> |
||||
|
<abp-input asp-for="LoginInput.RememberMe" class="mb-4" /> |
||||
|
</abp-column> |
||||
|
<abp-column class="text-end"> |
||||
|
<a href="@Url.Page("./ForgotPassword", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["ForgotPassword"]</a> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
<div class="d-grid gap-2"> |
||||
|
<abp-button type="submit" button-type="Primary" name="Action" value="Login" class="btn-lg mt-3">@L["Login"]</abp-button> |
||||
|
@if (Model.ShowCancelButton) |
||||
|
{ |
||||
|
<abp-button type="submit" button-type="Secondary" formnovalidate="formnovalidate" name="Action" value="Cancel" class="btn-lg mt-3">@L["Cancel"]</abp-button> |
||||
|
} |
||||
|
</div> |
||||
|
</form> |
||||
|
} |
||||
|
|
||||
|
@if (Model.VisibleExternalProviders.Any()) |
||||
|
{ |
||||
|
<div class="mt-2"> |
||||
|
<h5>@L["OrLoginWith"]</h5> |
||||
|
<form asp-page="./Login" asp-page-handler="ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" asp-route-returnUrlHash="@Model.ReturnUrlHash" method="post"> |
||||
|
@foreach (var provider in Model.VisibleExternalProviders) |
||||
|
{ |
||||
|
<button type="submit" class="btn btn-primary m-1" name="provider" value="@provider.AuthenticationScheme" title="@L["LogInUsingYourProviderAccount", provider.DisplayName]">@provider.DisplayName</button> |
||||
|
} |
||||
|
</form> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
@if (!Model.EnableLocalLogin && !Model.VisibleExternalProviders.Any()) |
||||
|
{ |
||||
|
<div class="alert alert-warning"> |
||||
|
<strong>@L["InvalidLoginRequest"]</strong> |
||||
|
@L["ThereAreNoLoginSchemesConfiguredForThisClient"] |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,166 @@ |
|||||
|
using Microsoft.AspNetCore.Authentication; |
||||
|
using Microsoft.AspNetCore.Identity; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Diagnostics; |
||||
|
using System.Linq; |
||||
|
using System.Security.Claims; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Account.Settings; |
||||
|
using Volo.Abp.Account.Web; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Identity; |
||||
|
using Volo.Abp.Identity.AspNetCore; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
using Volo.Abp.Settings; |
||||
|
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Account.Web.Pages.Account; |
||||
|
|
||||
|
[ExposeServices(typeof(Volo.Abp.Account.Web.Pages.Account.LoginModel))] |
||||
|
public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel |
||||
|
{ |
||||
|
public LoginModel( |
||||
|
IAuthenticationSchemeProvider schemeProvider, |
||||
|
IOptions<AbpAccountOptions> accountOptions, |
||||
|
IOptions<IdentityOptions> identityOptions, |
||||
|
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache) |
||||
|
: base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async override Task<IActionResult> OnPostAsync(string action) |
||||
|
{ |
||||
|
await CheckLocalLoginAsync(); |
||||
|
|
||||
|
ValidateModel(); |
||||
|
|
||||
|
ExternalProviders = await GetExternalProviders(); |
||||
|
|
||||
|
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin); |
||||
|
|
||||
|
await ReplaceEmailToUsernameOfInputIfNeeds(); |
||||
|
|
||||
|
await IdentityOptions.SetAsync(); |
||||
|
|
||||
|
var result = await SignInManager.PasswordSignInAsync( |
||||
|
LoginInput.UserNameOrEmailAddress, |
||||
|
LoginInput.Password, |
||||
|
LoginInput.RememberMe, |
||||
|
true |
||||
|
); |
||||
|
|
||||
|
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() |
||||
|
{ |
||||
|
Identity = IdentitySecurityLogIdentityConsts.Identity, |
||||
|
Action = result.ToIdentitySecurityLogAction(), |
||||
|
UserName = LoginInput.UserNameOrEmailAddress |
||||
|
}); |
||||
|
|
||||
|
if (result.RequiresTwoFactor) |
||||
|
{ |
||||
|
return await TwoFactorLoginResultAsync(); |
||||
|
} |
||||
|
|
||||
|
if (result.IsLockedOut) |
||||
|
{ |
||||
|
Alerts.Warning(L["UserLockedOutMessage"]); |
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
if (result.IsNotAllowed) |
||||
|
{ |
||||
|
var notAllowedUser = await GetIdentityUserAsync(LoginInput.UserNameOrEmailAddress); |
||||
|
if (await UserManager.CheckPasswordAsync(notAllowedUser, LoginInput.Password)) |
||||
|
{ |
||||
|
// 用户必须修改密码
|
||||
|
if (notAllowedUser.ShouldChangePasswordOnNextLogin || await UserManager.ShouldPeriodicallyChangePasswordAsync(notAllowedUser)) |
||||
|
{ |
||||
|
var changePwdIdentity = new ClaimsIdentity(AbpAccountAuthenticationTypes.ShouldChangePassword); |
||||
|
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.UserId, notAllowedUser.Id.ToString())); |
||||
|
if (notAllowedUser.TenantId.HasValue) |
||||
|
{ |
||||
|
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.TenantId, notAllowedUser.TenantId.ToString())); |
||||
|
} |
||||
|
|
||||
|
await HttpContext.SignInAsync(AbpAccountAuthenticationTypes.ShouldChangePassword, new ClaimsPrincipal(changePwdIdentity)); |
||||
|
|
||||
|
return RedirectToPage("ChangePassword", new |
||||
|
{ |
||||
|
returnUrl = ReturnUrl, |
||||
|
returnUrlHash = ReturnUrlHash, |
||||
|
rememberMe = LoginInput.RememberMe |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Alerts.Warning(L["LoginIsNotAllowed"]); |
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
Alerts.Danger(L["InvalidUserNameOrPassword"]); |
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
//TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
|
||||
|
var user = await GetIdentityUserAsync(LoginInput.UserNameOrEmailAddress); |
||||
|
|
||||
|
Debug.Assert(user != null, nameof(user) + " != null"); |
||||
|
|
||||
|
// Clear the dynamic claims cache.
|
||||
|
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId); |
||||
|
|
||||
|
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash); |
||||
|
} |
||||
|
|
||||
|
protected override Task<IActionResult> TwoFactorLoginResultAsync() |
||||
|
{ |
||||
|
// 重定向双因素认证页面
|
||||
|
return Task.FromResult<IActionResult>(RedirectToPage("SendCode", new |
||||
|
{ |
||||
|
returnUrl = ReturnUrl, |
||||
|
returnUrlHash = ReturnUrlHash, |
||||
|
rememberMe = LoginInput.RememberMe |
||||
|
})); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<IdentityUser> GetIdentityUserAsync(string userNameOrEmailAddress) |
||||
|
{ |
||||
|
return await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ?? |
||||
|
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress); |
||||
|
} |
||||
|
|
||||
|
protected async override Task<List<ExternalProviderModel>> GetExternalProviders() |
||||
|
{ |
||||
|
var schemes = await SchemeProvider.GetAllSchemesAsync(); |
||||
|
|
||||
|
var providers = schemes |
||||
|
.Where(x => x.DisplayName != null || x.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase)) |
||||
|
.Select(x => new ExternalProviderModel |
||||
|
{ |
||||
|
DisplayName = x.DisplayName, |
||||
|
AuthenticationScheme = x.Name |
||||
|
}) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var provider in providers) |
||||
|
{ |
||||
|
var localizedDisplayName = L[provider.DisplayName]; |
||||
|
if (localizedDisplayName.ResourceNotFound) |
||||
|
{ |
||||
|
localizedDisplayName = L["AuthenticationScheme:" + provider.DisplayName]; |
||||
|
} |
||||
|
|
||||
|
if (!localizedDisplayName.ResourceNotFound) |
||||
|
{ |
||||
|
provider.DisplayName = localizedDisplayName.Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return providers; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue